菜鸡的dfs学习 n-皇后问题
n-皇后问题(仅供菜鸡我自学)
题目描述
n-皇后问题是指将 n 个皇后放在 n∗n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
现在给定整数n,请你输出所有的满足条件的棋子摆法。
Input
共一行,包含整数n(n ≤ 10)。
Output
每个解决方案占n行,每行输出一个长度为n的字符 串,用来表示完整的棋盘状态。
其中”.”表示某一个位置的方格状态为空,”Q”表示某一个位置的方格上摆着皇后。
每个方案输出完成后,输出一个空行。
输出方案的顺序任意,只要不重复且没有遗漏即可。
分析
根据题意,我们可以知道每一行和每一列有且只能有一个皇后,所以我们可以用dfs枚举每一行或每一列,假定我们从0开始枚举行,那么我们可以设置三个bool数组 col、d、ud 分别表示当前位置所在列、对角线和反对角线上是否有皇后。
接下来让我们来看一下如何快速的判断两条对角线上是否有皇后,我们以棋盘的左、上边界建立直角坐标系,如图,我们可以用截距(b > 0)来唯一表示一条对角线
代码
#include<iostream>
using namespace std;
const int N = 10;
char a[N][N];
int n;
bool col[N], d[N * N], ud[N * N];
void dfs(int x) {
if(x == n) {
for(int i = 0; i < n; i ++) puts(a[i]);
puts("");
return ;
}
//从每一行第一个开始搜
for(int i = 0; i < n; i ++) {
if(!col[i] && !d[x + i] && !ud[x - i + N]) {
a[x][i] = 'Q';
col[i] = d[x + i] = ud[x - i + N] = true;
dfs(x + 1);
//回溯(恢复现场)
col[i] = d[x + i] = ud[x - i + N] = false;
a[x][i] = '.';
}
}
}
int main() {
cin >> n;
for(int i = 0; i < n; i ++)
for(int j = 0; j < n; j ++)
a[i][j] = '.';
dfs(0);
return 0;
}