n-皇后问题是指将 n 个皇后放在 n∗n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
现在给定整数n,请你输出所有的满足条件的棋子摆法。
输入格式
共一行,包含整数n。
输出格式
每个解决方案占n行,每行输出一个长度为n的字符串,用来表示完整的棋盘状态。
其中”.”表示某一个位置的方格状态为空,”Q”表示某一个位置的方格上摆着皇后。
每个方案输出完成后,输出一个空行。
输出方案的顺序任意,只要不重复且没有遗漏即可。
数据范围
1≤n≤9
输入样例:
4
输出样例:
.Q…
…Q
Q…
…Q.
…Q.
Q…
…Q
.Q…
这一道题是dfs的应用,算是中等难度的题目了,现在先给出我的代码,然后再给出我的解释
#include <cstring>
#include <iostream>
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是深度优先遍历,它可以将所有的方法都给试一遍,这也就解决了题目中要求我们将所有的方案都给输出的问题。
先来介绍 一下全局变量里面开的数组
其他的地方没什么好说的,我们直接来说一下dfs函数内部的情况吧。
dfs内部只有一个要解释的,就是怎么判断某个位置所在的行、列、以及正反斜线上没有其他的皇后。
这个时候,我们进行判断就需要我们之前在全局变量里面定义的bool数组了。
col这个数组很好解释,col[i] == false就表示第i行这一行里没有皇后。
那dg这个数组表示正斜线,那dg[n+u-i]是怎么来的呢
请看下图
udg这个数组表示反斜线,udg[u + i}是怎么得到的呢,我们再来看一下。
到这里,所有问题都给解决了,如果对dfs内部运行不太了解,可以看一下我的上一篇题解
全排列问题 <–点击这里
如果感觉有用,点个赞再走吧,给我持续用爱发电的动力