• 八皇后问题


    一、DFS实现N皇后

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int ans[10];//用于存放答案 
     4 int tot;//方案数 
     5 const int n=8;//N皇后问题 
     6 bool check(int c, int r){//判断前r行是否合法 
     7     for(int i=0; i<r; i++)
     8         if(ans[i]==c || (abs(ans[i]-c)==abs(i-r)))
     9             return false;
    10     return true;
    11 }
    12 void printans(){//将当前答案打印 
    13     cout<<"No. "<<tot<<endl;//方案数 
    14     for(int i=0; i<n; i++){//按要求打印方案 
    15         for(int j=0; j<n; j++){
    16             if(j==ans[i])cout<<1<<" ";
    17             else cout<<0<<" ";
    18         }
    19         cout<<endl;    
    20     }
    21 }
    22 void dfs(int r){ //r代表行号的选择,c代表列号的选择 
    23     if(r==n){
    24         tot++;
    25         printans();
    26         return;
    27     }
    28     for(int c=0; c<n; c++){
    29         if(check(c,r)){   //此方法验证合法性是通过函数,逐行与之前已放皇后比较,注意与下面方法的区别
    30             ans[r]=c;//将列的选择放在相应行数组里来存放答案 
    31             dfs(r+1);
    32         }
    33     }
    34 }
    35 int main()
    36 {
    37     dfs(0);
    38     return 0;
    39  } 

    二、DFS+回溯 实现8皇后

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n, ans[9];//存放答案 ans[i]=j表示第i行皇后位置为第j列 
     4 bool u[9], f1[16], f2[16]; //
     5 void pr(int d){
     6     for(int i=1; i<=d; i++)cout<<ans[i]<<" ";
     7     cout<<endl;
     8     return;
     9 }
    10 void dfs(int dep){
    11     if(dep>n)pr(dep-1);
    12     for(int i=1; i<=n; i++){                               //每1行都有8个位置(列)可以试放 
    13         if(u[i]==0 && f1[dep+i]==0 && f2[dep-i+n-1]==0){   //寻找可以放置皇后的位置:判断上方、斜线是否已被占,通过三个数组的值的判断 
    14             u[i]=1;  f1[dep+i]=1;  f2[dep-i+n-1]=1;        // 宣布占领第i列,和两条斜线 
    15             ans[dep]=i;                                    // 摆放皇后 
    16             dfs(dep+1);                                    //继续递归放置下一行的皇后 
    17             u[i]=0; f1[dep+i]=0; f2[dep-i+n-1]=0;          //当前皇后退出 
    18         }
    19     }
    20 }
    21 int main()
    22 {
    23     cin>>n;
    24     dfs(1);    //从第1行开始放置皇后的位置 
    25     return 0;
    26 }

    补充注释:u、f1、f2数组的含义分别是什么?

     1 /*
     2 下面这个程序是采用递归的方法回溯解八皇后问题,我们知道,国际象棋里的皇后可以吃到与之处于同一直线上的子,包括:横线、竖线、右上至左下的斜线、左上至右下的斜线,一共四条线。而这个算法是一行一行的找合适放置皇后的位置,每行只放一个皇后,所以横线这个限制已经满足,接下来考虑另外三个限制,即:
     3 竖线、右上至左下的斜线、左上至右下的斜线
     4 办法就是用三个数组来记录,如下:
     5   int u[N+1]; // 同栏是否有皇后,0表示没有,1表示有
     6   int f1[2*N+1]; // 右上至左下是否有皇后,0表示没有,1表示有
     7   int f2[2*N+1]; // 左上至右下是否有皇后,0表示没有,1表示有
     8 因为N(比如N=8)皇后问题中,一共有:
     9 竖线N条、
    10 右上至左下的斜线2*N-1条、
    11 左上至右下的斜线2*N-1条、
    12 又由于这个程序中计数不是从0开始,而是从1开始的,
    13 所以,u[N+1]而不是u[N],
    14 同理,f1[2*N+1]而非f1[2*N-1],f2[2*N+1]而非f2[2*N-1]
    15 这样,可以理解这三个数组的长度为什么这样设置了
    16 接下来,就很容易理解这三个数组的值怎么设置了
    17 例如u[i]=1,表示第i列上已经有皇后了(我们不需要理会这个皇后在第几行)
    18 同理可知f1和f2的含义。
    19 如果我们在棋盘的第i行,第j列放置了一个皇后,
    20 那么,除了将queen[i] = j;// 设定为占用
    21 我们还需将u[j] = f1[i+j] = f2[i-j+N] = 1;
    22 举一个具体的例子:
    23 ..Q.....
    24 Q.......
    25 .......Q
    26 ........
    27 ........
    28 ........
    29 ........
    30 ........
    31 当前我们已经在棋盘的前3行放上了3个皇后,
    32 那么,这三个数组的情况如下:
    33        0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    34 u:     0 1 0 1 0 0 0 0 1
    35 f1:    0 0 0 1 1 0 0 0 0 0 0  1  0  0  0  0  0  0
    36 f2:    0 0 0 1 0 0 0 1 0 0 1  0  0  0  0  0  0  0
    37 接下来,去第4行上找一个合适的位置放置第4个皇后,
    38 那么我们就必须避开前面3个皇后的影响,通过对比这三个数组即可。
    39 */

     回溯法与深度优先搜索的关系

  • 相关阅读:
    python 将png图片格式转换生成gif动画
    JetBrains系IDE的设置Pycharm PHPStorm
    Nginx 静态页面POST 请求提示405 Not Allowed
    安装SSL证书 and 根域名跳转www域名
    Linux 安装qt5-designer并集成到Pycharm
    Deepin 自动挂载win NTFS磁盘
    Nginx+DNS负载均衡实现
    swoole websocket服务推送
    Linux版 php5.4 升级php7
    百度 Javascript开发 API
  • 原文地址:https://www.cnblogs.com/tflsnoi/p/13688487.html
Copyright © 2020-2023  润新知