n-皇后问题【所用算法——dfs】

n-皇后问题是指将 n 个皇后放在 n∗n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
n-皇后问题【所用算法——dfs】_第1张图片
现在给定整数n,请你输出所有的满足条件的棋子摆法。

输入格式
共一行,包含整数n。

输出格式
每个解决方案占n行,每行输出一个长度为n的字符串,用来表示完整的棋盘状态。

其中”.”表示某一个位置的方格状态为空,”Q”表示某一个位置的方格上摆着皇后。

每个方案输出完成后,输出一个空行。

输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围
1≤n≤9
输入样例:
4
输出样例:
.Q…
…Q
Q…
…Q.

…Q.
Q…
…Q
.Q…


这一道题是dfs的应用,算是中等难度的题目了,现在先给出我的代码,然后再给出我的解释

#include 
#include 

using namespace std;

const int N = 20;

int n;
char g[N][N];//读入图
bool col[N], dg[N], udg[N];//col表示列,dg正斜线,udg反斜线

void dfs(int u){
    if (u == n){//当进行到n的时候,输出数据
        for (int i = 0; i < n; i ++ ) puts(g[i]);//输出一行的字符串
        puts("");//换行操作
        return;
    }
    
    for(int i = 0; i < n; i ++ )//i表示列
        if (!col[i] && !dg[n + u - i] && !udg[u + i]){
            //值为0表示当前位置不管是横着、竖着、斜着都没人,那就可以填上一个皇后
            g[u][i] = 'Q';//给这个位置安上一个皇后
            col[i] = dg[n + u - i] = udg[u + i] = true;//这个位置所在的行列斜线都被占了
            dfs(u + 1);//进行下一行
            g[u][i] = '.';//还原
            col[i] = dg[n + u - i] = udg[u + i] = false;//还原
        }
}

int main(){
    cin >> n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            g[i][j] = '.';//开始的时候,每个位置都没有皇后
            
    dfs(0);//还是dfs
    
    return 0;
}

在国际象棋中,皇后有很大的本事,可以沿着横线走,也可以沿着斜线走,所以基于这一点,我们要在一个n*n的棋盘上放置n个皇后,一定不能让他们在同一行,同一列,同一斜线上,不然那还不得打起来。

对于这一题,我们应当使dfs算法是毋庸置疑的,那我们就来聊一聊该怎么使用dfs

我们知道dfs是深度优先遍历,它可以将所有的方法都给试一遍,这也就解决了题目中要求我们将所有的方案都给输出的问题。

先来介绍 一下全局变量里面开的数组
n-皇后问题【所用算法——dfs】_第2张图片
其他的地方没什么好说的,我们直接来说一下dfs函数内部的情况吧。

dfs内部只有一个要解释的,就是怎么判断某个位置所在的行、列、以及正反斜线上没有其他的皇后。
这个时候,我们进行判断就需要我们之前在全局变量里面定义的bool数组了。

col这个数组很好解释,col[i] == false就表示第i行这一行里没有皇后。
那dg这个数组表示正斜线,那dg[n+u-i]是怎么来的呢
请看下图
n-皇后问题【所用算法——dfs】_第3张图片
udg这个数组表示反斜线,udg[u + i}是怎么得到的呢,我们再来看一下。
n-皇后问题【所用算法——dfs】_第4张图片

到这里,所有问题都给解决了,如果对dfs内部运行不太了解,可以看一下我的上一篇题解
全排列问题 <–点击这里

如果感觉有用,点个赞再走吧,给我持续用爱发电的动力

你可能感兴趣的:(n-皇后问题【所用算法——dfs】)