zoukankan      html  css  js  c++  java
  • ACWing843. n-皇后问题

    题目

    分析一

    本问题可以按照全排列的dfs来写。生成一个排列数,下标 i 对应第 i 行,其上的数字代表放哪一列。

    代码

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N = 20;//这里开到20
     5 bool col[N],dg[N],udg[N];
     6 char path[N][N];
     7 int n;
     8 
     9 void dfs(int u){
    10     if(u == n){
    11         for(int i = 0;i < n;i++){
    12             puts(path[i]);  //直接按照一行输出
    13         }
    14         puts("");
    15         return;
    16     }
    17     //遍历列,查看u行放哪一列
    18     for(int i = 0;i < n;i++){
    19         if(!col[i] && !dg[u+i] && !udg[n+i-u]){
    20             path[u][i] = 'Q';
    21             col[i] = dg[u+i] = udg[n+i-u] = true;
    22             dfs(u+1);
    23             path[u][i] = '.';
    24             col[i] = dg[u+i] = udg[n+i-u] = false;
    25         }
    26     }
    27     
    28 }
    29 int main(){
    30     cin>>n;
    31     for(int i = 0;i < n;i ++){
    32         for(int j = 0;j < n;j++){
    33             path[i][j] = '.';
    34         }
    35     }
    36     dfs(0);
    37     return 0;
    38 }

    上面代码 u 表示遍历行,i 表示遍历列

    技巧:

    1.主对角线标记数组dg。按照 y总说法将其按照直角坐标理解记忆:

    主对角线方程:y = -x + b,副对角线方程:y = x + b

    进而得到,主:y + x = b,副:y - x = b。对应代码 主:i + u = b ,副: i - u = b,而b是一定的。所以判断是否位于主对对角线或副对角线。只需看 i+u 或 i - u是否被访问过。这里对于副对角线的i-u还要加上偏移量n,这是因为减法会为负数,n - i + u  = n + b 等式不变,依然能表示副对角线。

    2. 对于二维字符数组,用puts可直接打印一行

    3. 为什么const int N 要开到 20,因为主、副对角线的访问数组 是 x + y ,而 x 的下标就是1—9

     分析二(按照位置坐标搜素)

    代码

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N = 20;
     5 bool row[N],col[N],dg[N],udg[N];
     6 char path[N][N];
     7 int n;
     8 
     9 //x,y表示坐标,s表示已经放入的皇后数量
    10 //每一行开始遍历
    11 void dfs(int x,int y ,int s){
    12     if(y == n) y = 0,x++; //走到有边界,回来   这里不要dfs(x+1,0,s),因为 x 可能本身就为 n ,超出内存 改为:{dfs(x+1,0,s);return;} 
    13     //行遍历结束
    14     if(x == n){
    15         //查看是否放了n个皇后
    16         if(s == n){
    17             for(int i = 0;i < n;i++){
    18                 puts(path[i]);
    19             }
    20             puts("");
    21         }
    22         return;
    23     }
    24     
    25     //该位置不放皇后
    26     dfs(x,y+1,s);
    27     
    28     //该位置放皇后
    29     if(!row[x] && !col[y] && !dg[x+y] && !udg[x-y+n]){
    30         path[x][y] = 'Q';
    31         row[x] = col[y] = dg[x+y] = udg[x-y+n] = true;
    32         dfs(x,y+1,s+1);
    33         path[x][y] = '.';
    34         row[x] = col[y] = dg[x+y] = udg[x-y+n] = false;
    35     }
    36 }
    37 
    38 int main(){
    39     cin>>n;
    40     for(int i = 0;i < n;i ++){
    41         for(int j = 0;j < n;j++){
    42             path[i][j] = '.';
    43         }
    44     }
    45     dfs(0,0,0);
    46     return 0;
    47 }
  • 相关阅读:
    【angularJS】启动(bootstrap)机制
    【angularJS】定义模块angular.module
    【angularJS】简介
    .NET AutoMapper学习记录
    WebAPI学习
    【MongoDB】在C#中使用
    RabbitMQ介绍及windows下安装使用
    【MongoDB】初识
    php命名空间(nameSpace)的使用详解
    魔术方法
  • 原文地址:https://www.cnblogs.com/fresh-coder/p/14429063.html
Copyright © 2011-2022 走看看