[题] n-皇后问题 #深搜 #DFS

题目 AcWing 843. n-皇后问题

代码

#include
using namespace std;
const int N = 20;
int n, p[N];
char g[N][N];
bool col[N], dg[N], udg[N];
void D (int u){

    if(u == n){
        for(int j = 0; j < n; j ++ )
            puts(g[j]);
        cout << endl;
        return ;
    }

    for(int i = 0; i < n; i ++)
        if( !col[i] && !dg[u + i] && !udg[n - u + i] ){
            g[u][i] = 'Q';
            col[i] = dg[u + i] = udg[n - u + i] = 1;
            p[u] = i;
            D(u + 1);
            g[u][i] = '.';
            col[i] = dg[u + i] = udg[n - u + i] = 0;
        }
    return ;
}
int main(){
    cin >> n;
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            g[i][j] = '.';
    D(0);
    return 0;
}
/*
*0 搜索方式 : 深搜。
    具体操作:先遍历 第0行 可以放皇后的所有位置,再遍历 第1行 可以放皇后的位置...依次类推到 第n行。

*1 
    补英文:column   列
            diagonal 对角线
            row      行
*2 这里 u+i  以及  n-u+i  分别是  (u,i)所在的对角线(这样的 /)  以及  反对角线(这样的 \)
    具体推导是: 令 (u, i) 为 在坐标轴上的 (x, y);
                (x, y)分别在对角线 y = x + b 以及 反对角线 y = -x + b 上。
                坐标轴上的 y=x+b  =>  b=x-y  =>  b=n+x-y  (防止出现负数) ;
                      以及  y=-x+b  =>  b=x+y 。

                这时的 b 就是 (u,i) 所在的 对角线(或反对角线)的唯一编号;
                这样下来,在同一对角线的所有点就有了一样的唯一编号。(具体多少不重要u, i 可调换)
*3 p[u] 表示第u 行放的皇后的位置。
*4 时间是 18ms 左右;
*/

/*
    *2点中说的对角线上的 u, i 调换对比版,答案是一样的。
    不用纠结 对角线和反对角线 这里的坐标序号之类的。
#include
using namespace std;
const int N = 20;
int n, p[N];
char g[N][N];
bool col[N], dg[N], udg[N];
void D (int u){

    if(u == n){
        for(int j = 0; j < n; j ++ )
            puts(g[j]);
        cout << endl;
        return ;
    }

    for(int i = 0; i < n; i ++)
        if( !col[i] && !dg[i + u] && !udg[n - i + u] ){
            g[u][i] = 'Q';
            col[i] = dg[i + u] = udg[n - i + u] = 1;
            p[u] = i;
            D(u + 1);
            g[u][i] = '.';
            col[i] = dg[i + u] = udg[n - i + u] = 0;
        }
    return ;
}
int main(){
    cin >> n;
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            g[i][j] = '.';
    D(0);
    return 0;
}

*/
/*
原始的 “选与不选”搜索方法;
从(0,0) 一直依次遍历到 (n,n),对于每一个格子的操作是(放皇后或不放皇后);
时间是 107ms左右 ,不如上一个算法;
#include
using namespace std;
const int N = 20;
int n ;
char g[N][N];
bool col[N], dg[N], udg[N], row[N];
void D (int x, int y, int s){
    if(y == n){
        x ++;
        y = 0;
    }

    if(x == n){
        if(s == n){
            for(int i = 0; i < n; i ++)
                puts(g[i]);
                cout << endl;
        }
        return ;
    }

    D(x, y  + 1, s);

    if(!row[x] && !col[y] && !dg[n - x + y] && !udg[x + y]){
        row[x] = col[y] = dg[n - x + y] = udg[x + y] = 1;
        g[x][y] = 'Q';
        D(x, y + 1, s + 1);
        g[x][y] = '.';
        row[x] = col[y] = dg[n - x + y] = udg[x + y] = 0;
    }
}
int main(){
    cin >> n;
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < n; j ++)
            g[i][j] = '.';
    D(0, 0, 0);
    return 0;
}
*/

你可能感兴趣的:(深度优先,算法,c++)