【AcWing——搜索与图论:深度优先搜索】843. n-皇后问题
这是第二次实现n皇后,之前使用hash实现的,当时只用了一种方法,就是提前看出每行只有一个皇后,然后考虑上下攻击和对角线攻击,这里使用两种方法,一种是设定每行只有一个皇后;另一种方法是直接暴解,遍历整个n*n的矩阵呢个,考虑每个格子放还是不放。
// 方法一:设定每行只有一个皇后,找全排列
#include <iostream>
using namespace std;
const int N = 20;
int n;
char outStr[N][N];
bool col[N];//当前列是否已占用
bool dg[N], udg[N];//主对角和次对角
void dfs(int start) {
//递归的出口
if (start == n) {
for (int i = 0; i < n; ++i) puts(outStr[i]);
puts("");
return;
}
//递归的出口
for (int i = 0; i < n; ++i) {
//start为行, i为列;
//代码思考时就已经考虑每行只放一个皇后了,只需要考虑上下和对角线攻击了
//主对角用start + i的原因:y = x + b(直线公式)
//次对角用n - start + i的原因:y = -x + b(直线公式),但这里-x应该会负数,所以使用n-(-x+b)
//保证主次对角线纵坐标y是相同的,就变成了下面的样子
if (!col[i] && !dg[start + i] && !udg[n - (-start + i)]) {
outStr[start][i] = 'Q';
col[i] = dg[start + i] = udg[n - (-start + i)] = true;
dfs(start + 1);
col[i] = dg[start + i] = udg[n - (-start + i)] = false;
outStr[start][i] = '.';
}
}
}
int main() {
cin >> n;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
outStr[i][j] = '.';
dfs(0);
return 0;
}
// 方法二:直接暴搜n*n网格
#include <iostream>
using namespace std;
const int N = 20;
int n;
char outStr[N][N];
bool row[N], col[N];//当前行和列是否已占用
bool dg[N], udg[N];//主对角和反对角
void dfs(int x, int y, int queenCount) {
if (n == y) y = 0, ++x;//当列到最后一列,返回到下一行的第一列
if (n == x) {
if (n == queenCount) {
for (int i = 0; i < n; ++i) puts(outStr[i]);
puts("");
}
return;
}
// 当前格子不放皇后
dfs(x, y + 1, queenCount);//跳转到下一个格子
// 当前格子放皇后
if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n]) {
outStr[x][y] = 'Q';
row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;
dfs(x, y + 1, queenCount + 1);
row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;
outStr[x][y] = '.';
}
}
int main() {
cin >> n;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
outStr[i][j] = '.';
dfs(0, 0, 0);//从左上角开始搜,再记录一下当前总共有几个皇后
return 0;
}