【アルゴリズム設計・解析】バックトラッキング法(ソート、サブセットサム、TSP、nクイーン)

レベル 1: アレンジメント

ここに画像の説明を挿入します
サンプル入力

4  2  

サンプル出力

A B
A C
A D
B A
B C
B D
C A
C B
C D
D A
D B
D C 

分析:
これは、あらゆる状況に対する列挙型の解決コードであることに注意してください

//#include<bits/stdc++.h>
#include<stdio.h>
//using namespace std;
int m,n;
int an[10010],a[10010],ck[10010];
void cal(int x){
    
    
	if(x==n){
    
    
		for(int i = 0;i<n;i++){
    
    
           printf("%c",an[i]);  if(i!=n-1) printf(" ");
        } 
		printf("\n");
		return;
	}else{
    
    
		for(int i = 0 ; i < m;i++){
    
    
			if(ck[i]!=1){
    
    
				an[x] = a[i];
				ck[i]	= 1;
				cal(x+1);
				ck[i] = 0;
			} 
		}	
	}
}
int main(){
    
    
	scanf("%d%d",&m,&n);
	for(int i = 0; i <m;i++){
    
    
		a[i] = i+ 'A';
		ck[i] = 0;
	}
	cal(0);
	return 0;
}

レベル 2: サブセット

ここに画像の説明を挿入します
サンプル入力

5 10
2 2 6 5 4  

サンプル出力

2 2 6
6 4 

アイデア:サブセット ツリーを使用して、条件を満たすサブセットの制限条件を見つけるだけです。

解決策コード:

#include<stdio.h>
//#include<bits/stdc++.h>
//using namespace std;
int a[20],an[20], ck[20];
int n,c; 
int f = 0;
void solve(int x,int sum,int st){
    
    
	if(sum>c) return; //剪枝
	if(sum==c){
    
    
		f = 1;//标记是不是  存在解
		for(int i = 0; i <x;i++){
    
      //输出
            printf("%d",an[i]); if(i!=x-1) printf(" ");
        } printf("\n");	
		return;
	}else{
    
    
		for(int i = st; i <n;i++){
    
      //解空间树结点下的结点  是有范围的
			if(ck[i]!=1){
    
    
				an[x] = a[i]; ck[i] = 1;
				//cout<<"i: "<<i<<" "<<a[i]<<" "<<sum<<" "<<ck[i]<<endl;
				solve(x+1,sum+a[i],i);
				ck[i] = 0;
			}
		}
	}
}
int main(){
    
    
	scanf("%d%d",&n,&c);
	for(int i = 0; i < n;i++) scanf("%d",&a[i]); 
	solve(0,0,0);
	if(!f) printf("No Solution!"); 
	return 0;
} 

レベル 3: TSP の質問

ここに画像の説明を挿入します
入力形式:
最初の行に「n」と入力します。これは、n 個の都市があることを意味します。
次に、n 行の各行に n 個の数値を入力します。i 行、j 列の値は、都市 i から都市 j までの距離を表します。0 は都市間に接続がないことを示します。注: 始点と終点は両方とも 1 n<
です
。 7、都市間の距離
出力形式は
100 を超えません。最初の行は最小移動コストを出力し、
2 行目は移動経路に入ります
(最短の移動経路が 1 つだけであることが保証されます)。

サンプル入力

4  
0 30 6 4
30 0 5 10
6 5 0 20
4 10 20 0  

サンプル出力

25
1 3 2 4 1

コード 1:

// #include<bits/stdc++.h>
// using namespace std;
#include<stdio.h>
int a[110][110];
int n;
int f[110],p[110],pd[110];
int minn = 1000010,sum = 0,len = 1;
void solve(int x){
    
    
    if(len==n&&a[x][1]!=0){
    
     //就是 最后要回到起点
        if(sum+a[x][1]<minn){
    
    
            for(int i = 0; i<n;i++){
    
    
                pd[i] = p[i];  //存一下  不断更新  找最小的
            }
            minn = sum +a[x][1];
        }
    }
    if(sum>minn) return ;
    if(len<n){
    
    
        for(int j = 1; j <= n;j++){
    
    
            if(f[j]==0&&a[x][j]!= 0){
    
    
                sum += a[x][j]; p[len] = j;
                len++;  f[j] = 1;
                
                solve(j);
                f[j] = 0;
                len--;
                sum -= a[x][j];
            }
        }
    }
}
int main(){
    
    
    scanf("%d",&n);
    for(int i = 1; i <= n;i++){
    
    
        for(int j = 1; j <= n;j++){
    
    
             scanf("%d",&a[i][j]);
        }
    }
    f[1] = 1;  solve(1);
    printf("%d\n",minn);
    printf("1 ");
    for(int i = 1; i < n;i++)  printf("%d ",pd[i]);
    printf("1");
    return 0;
}

コード 2:

 #include <stdio.h>
#define MAX 100 

int n;
int b[8]={
    
    1,2,3,4,5,6,7};
int a[MAX][MAX],x[8];
int mindis=1000;

void swap(int &a,int &b)
{
    
    
	int t=a;
	a=b;
	b=t;
}

void dfs(int i,int dis)
{
    
    
	if(dis>=mindis)
		return;
	else if(i==n)
	{
    
    
		if(dis+a[b[i-1]][1]<mindis)
		{
    
    
			mindis=dis+a[b[i-1]][1];
			for(int j=1;j<n;j++)
				x[j]=b[j];
		}
		return;
	}
	else
	{
    
    
		for(int j=i;j<n;j++)
		{
    
    
			swap(b[i],b[j]);
			dfs(i+1,dis+a[b[i-1]][b[i]]);
			swap(b[i],b[j]);
		}
	}
}
int main() {
    
    
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
    
    
    	for(int j=1;j<=n;j++)
    		scanf("%d",&a[i][j]);
	}
	
	dfs(1,0);
	printf("%d\n",mindis);
	printf("1");
	for(int i=1;i<n;i++)
		printf(" %d",x[i]);
	printf(" 1");
    return 0;
}

レベル 4: n クイーン問題

タスクの説明:
N*N の正方形のチェス盤上に N 個のクイーンを配置し、互いに攻撃しないようにします (つまり、どの 2 つのクイーンも同じ行、同じ列に配置することはできず、同じ位置に配置することもできません)。チェス盤の境界線から 45 度の角度。オンライン。
あなたのタスクは、指定された N に対して正当な配置方法がいくつあるかを調べることです。
入力形式に
は複数の行があり、各行には正の整数 N≤10 があり、その数を示します。チェス盤とクイーン; N=0 の場合、終了を示します
出力形式に
は複数の行があり、各行は正の整数を持ち、入力行に対応するクイーンの異なる配置の数を示します。

タスクの説明:
N*N の正方形のチェス盤上に N 個のクイーンを配置し、互いに攻撃しないようにします (つまり、どの 2 つのクイーンも同じ行、同じ列に配置することはできず、同じ位置に配置することもできません)。チェス盤の境界線から 45 度の角度。オンライン。
あなたの課題は、指定された N に対して正当な配置方法がいくつあるかを見つけることです。

入力形式
複数の行があり、各行にはチェス盤とクイーンの数を示す正の整数 N≤10 があり、N=0 の場合は終了を意味します。

出力形式に
は複数の行があり、各行は正の整数を持ち、入力行に対応するクイーンの異なる配置の数を示します。

サンプル入力

1  
8
5  
0

サンプル出力

1  
92
10

アイデア:
実際、スペース ツリーを解く際の制限は、この解セットの現在のノードの行、スラッシュ、およびバックスラッシュに既にクイーンが存在するかどうかを判断することです。

解決策コード:

//#include<bits/stdc++.h>
#include<stdio.h>
//using namespace std;
const int N = 20;
int n;
int col[N],dg[N],udg[N];
int ans;
void solve(int u){
    
    
     if(u==n){
    
    
         ans++; return;
     }else{
    
    
         for(int i = 0; i< n;i++){
    
    
                 if(!col[i]&&!dg[u+i]&&!udg[u+n-i]){
    
    
                  col[i] = dg[u+i] = udg[u+n-i] = true;
                  solve(u+1);
                  col[i] = dg[u+i] = udg[u+n-i] =  false;
              }
         }
          
     }
}
int main(){
    
    
     while(~scanf("%d",&n)&&n){
    
    
         ans = 0;
         solve(0);
        printf("%d\n",ans); 
     }
    return 0;    
} 

レベル 5: 0-1 バックパック

**アイデア:** 動的プログラミングについては、多くを語ることはありません。

解決策コード:

#include<stdio.h>
// #include<bits/stdc++.h>
// using namespace std;
int n,c,w[110],v[110];
int f[110][110]; 
int main(){
    
    
    scanf("%d%d",&n,&c);
    for(int i = 1; i <= n;i++){
    
    
            scanf("%d",&w[i]);
    }
    for(int i = 1; i <= n;i++){
    
    
            scanf("%d",&v[i]);
    }
    for(int i = 1; i <= n;i++){
    
    
            for(int j = 0; j <= c;j++){
    
    
                    f[i][j] = f[i-1][j];
                    if(j>=w[i]&&(f[i-1][j-w[i]]+v[i] > f[i][j])) f[i][j] = f[i-1][j-w[i]]+v[i] ;
            }             
    }
    printf("%d",f[n][c]);
    return 0;    
} 

おすすめ

転載: blog.csdn.net/qq_52626583/article/details/124818199