搜索与回溯算法

1素数环:12020个数摆成一个环,要求相邻的两个数的和是一个素数。

算法分析
解空间:从1开始,每个空位有20种可能,只要填进去的数合法:与前面的数不相同;
约束条件:与左边相邻的数的和是一个素数,且没有被用过。
边界条件:第20个数还要判断和第1个数的和是否素数,是就输出,不是就回溯
【算法流程】
1、数据初始化;  
2、递归填数:判断第i个数填入是否合法;
A、如果合法:填数;
     判断是否到达目标(20个已填完):是,打印结果;
     不是,递归填下一个;
B、如果不合法:选择下一种可能;
代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath> 
 4 using namespace std;
 5 
 6 int a[10],tot=0;
 7 bool b[10];
 8 
 9 bool su(int x,int y){
10     if(x==1) return 1;
11     int k=2;int i=x+y;
12     while(k<=sqrt(i)&&i%k!=0)k++;
13     if(k>sqrt(i)) return 1;
14     else return 0;
15 }
16 
17 int print(){
18     tot++;
19     for(int i=1;i<=6;i++){
20         cout<<a[i]<<" ";
21     }cout<<endl;
22 }
23 
24 int Search(int k){
25     for(int i=1;i<=6;i++){
26         if(su(a[k-1],i)&&!b[i]){
27             a[k]=i;
28             b[i]=true;
29             if(k==6){
30                 if(su(a[6],a[1]))
31                 print();
32             }
33             else Search(k+1);
34             b[i]=false;
35         }
36     }
37 }
38 
39 int main(){
40     Search(1);
41     cout<<tot<<endl;
42     return 0;
43 }
View Code
【例2设有n个整数的集合{1,2,,n},从中取出任意r个数进行排列(r<n),试列出所有的排列。
 算法分析
解空间:从第1个位置开始,每个空位有n种选择
约束条件:只要没有被用过就可
边界条件:够了r 个数就可以输出
代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 int a[10],n,r,tot;
 6 int b[10];
 7 
 8 int print(){
 9     tot++;
10     for(int i=1;i<=r;i++)
11       cout<<a[i]<<" ";
12     cout<<endl;
13 }
14 
15 int Search(int k){
16     for(int i=1;i<=n;i++){
17         if(!b[i]){
18             a[k]=i;
19             b[i]=true;
20             if(k==r) print();
21             else Search(k+1); 
22             b[i]=false;
23         }
24     }
25 }
26 
27 int main()
28 {
29     cin>>n>>r;
30     Search(1);
31     cout<<tot<<endl;
32     return 0;
33 }
View Code
【例2扩展设有n个整数的集合{1,2,,n},从中取出任意r个数进行组合(r<n),试列出所有的组合。
代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 int a[100],n,m,tot;
 6 bool b[100];
 7 
 8 int Search(int k){
 9     if(k>m){
10         tot++;
11         for(int i=1;i<=m;i++){
12             cout<<a[i]<<" ";
13         }cout<<endl;
14     }
15     else{
16         for(int i=1;i<=n;i++)
17             if(i>=a[k-1]&&!b[i]){
18                 a[k]=i;
19                 b[i]=true;
20                 Search(k+1);
21                 b[i]=false;
22             }
23     }
24 }
25 
26 int main(){
27     cin>>n>>m;
28     Search(1);
29     cout<<tot<<endl;
30     return 0;
31 }
View Code
【例3任何一个大于1的自然数n,总可以拆分成若干个小于n自然数之和。
【问题分析】
(1)本题需要注意,任给自然数n,能否给出所有不同的拆分。
10=3+7与10=7+3是同一种拆分。
(2)如何求出所有的拆分。
下面分析拆分过程:
取n=7来说明:
第一步:将n拆分为2项之和
7=1+6
7=2+5
7=3+4
拆分的特点是第2个加数总大于第1个加数。
第二步:只要第2个加数仍然大于1,就可按第一步重复拆分,例如:
7=1+6 可以继续拆分获得
7=1+1+5
7=1+2+4
7=1+3+3
其中7=1+1+5又可继续拆分获得
7=1+1+1+4
7=1+1+2+3
 
..................
 
最后获得共14种拆分法
 
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 int a[100],n,tot=1;
 6 
 7 int print(int t){
 8     /*tot++;*/
 9     cout<<n<<"=";
10     for(int i=1;i<=t-1;i++){
11         cout<<a[i]<<"+";
12     }cout<<a[t]<<endl;
13 }
14 
15 void Search(int s,int t){
16     for(int i=1;i<=s;i++){
17         if(i>=a[t-1]&&i<n){
18             a[t]=i;
19             s-=i;
20             if(s==0) print(t);
21             else Search(s,t+1);
22             s+=i;
23         }
24     }    
25 }
26 
27 int main(){
28     cin>>n;
29     Search(n,1);
30     /*cout<<tot<<endl;*/
31     return 0;
32 }
View Code
例4:n皇后问题
   在n×n的国际象棋棋盘上,放置n个皇后,使任何一个皇后都不能吃掉另一个,需满足的条件是:
  同一行、同一列、同一对角线上只能有一个皇后。求所有满足要求的放置方案。当n=4时有2种放置方法
(2,4,1,3),(3,1,4,2)
 
算法描述:
1.产生一种新放法
2.冲突,继续找,直到找到不冲突----不超范围
3.if 不冲突 then   k<nàk+1
                k=nà一组解
4.if 冲突 then 回溯
 
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 bool b[100],c[100],d[100];
 6 int a[100],n,tot;
 7 
 8 int print(){
 9     tot++;
10     for(int i=1;i<=n;i++){
11         cout<<a[i]<<" ";
12     }cout<<endl;
13 }
14 
15 int Search(int k){
16     for(int i=1;i<=n;i++){
17         if(!b[i]&&!c[k+i]&&!d[k-i+n-1]){
18             a[k]=i;
19             b[i]=true;
20             c[k+i]=true;
21             d[k-i+n-1]=true;
22             if(k==n) print();
23             else Search(k+1);
24             b[i]=false;
25             c[k+i]=false;
26             d[k-i+n-1]=false;
27         }
28     }
29 }
30 
31 int main()
32 {
33     cin>>n;
34     Search(1);
35     cout<<tot<<endl;
36     return 0; 
37 }
View Code
 
原文地址:https://www.cnblogs.com/wsdestdq/p/6754371.html