• 搜索与回溯算法


    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
     
  • 相关阅读:
    运用VS制作安装包
    return的总结
    Swift UIAlertController、UISegmentedControl
    Swift 菊花、UIPageControl和UIProgressView
    Swift UITextField各种属性的设置
    Swift 发送邮件和发短信
    Swift GCD
    swift 定义枚举和结构体 及使用
    iOS怎么来实现关闭自动锁屏
    IOS开发 清空数组正确方法
  • 原文地址:https://www.cnblogs.com/wsdestdq/p/6754371.html
Copyright © 2020-2023  润新知