一、题目介绍
八皇后问题是指将 8个皇后放在 8 * 8 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个
皇后都不能处于同一行、同一列或同一斜线上.
现将皇后数量,棋盘长度以及棋盘宽度换为正整数n。列出所有可能保证任意皇后不被攻击。
输入格式
共一行,包含整数 n。
输出格式
每个解决方案占 n行,每行输出一个长度为 n 的字符串,用来表示完整的棋盘状态。其中 0表示某
一个位置的方格状态为空,1 表示某一个位置的方格上摆着皇后。
二、解决思路
本题也是借鉴了acwing当中y总的思路
突破点1:坐标表示皇后
既然是在一个n * n的带格子的地图上放置皇后,那么不妨将这些点以坐标形式呈现。
例如第一行第三列有一个皇后,我们可以将这个皇后位置设置为(0, 2),意为第一排第三列。
输出的时候直接判断该点是否为1,为1就代表有皇后,为0表示没皇后,输出出来一目了然。
突破点1的引申:树形结构的形成
假设棋盘大小是4 * 4
起初我们用四个空位置表示放入皇后的位置,例如2 4 1 3,就分别表示:皇后的位置出现在第1排第2列(0, 1),第2排第4列(1, 3),第3排第1列(2, 0), 第4排第3列(3, 2).
这个问题就变成一个带有对角线限制的全排列问题
由于从第一排开始到最后一排,每一列都会用1,2,3,4表示皇后在该行的第几列,因此我们用树形结构表示这一变化。横着代表列的变化,可以用for循环实现,纵向我们采用递归,来实现行的变化。(❌代表剪枝)
突破点2:对角线突破
对角线分为正对角线和反对角线,如下图所示:
正对角线满足公式:y = x + b 反对角线满足公式: y = -x + c(其中x是行,y对应列)
核心点:任意两个点不在对角线上意味着 行和列的和 或者 列减行的差 分别不为同一个常数。(y + x = c,y - x = b)。
从核心点开始引申:那么怎么如何在运行程序的时候保存住这个常数呢?总不能设置很多临时变量吧?
因此我们考虑设置数组来保存,只要是以这个常数为下标的数组值统统设置为true,数组的其他数据设置为false,例如(0,2)和(1, 1)肯定在一条对角线上(正对角线),因此列+行就是2,以2为下标的数组数据直接设置成true,若有x,y值满足则跳过。
// 定义正对角线,反对角线以及列.
bool dg[N * 2], udg[N * 2], col[N];
// N代表棋盘的长和宽
// i是列数,0就是第一列。cur是行数
for (int i = 0; i < N; i++) {
if (!col[i] && !dg[i + cur] && !udg[i - cur + N]) {
arr[cur][i] = 1;
col[i] = dg[i + cur] = udg[i - cur + N] = true;
dfs(cur + 1);
arr[cur][i] = 0;
col[i] = dg[i + cur] = udg[i - cur + N] = false;
}
}
易错点:当列数减去行数的时候,难免会出现负数的情况,而数组下标不可能为负数,因此我们统一加上棋盘的长度(即i - cur + N),因为最小的负数也是(3, 0),即第四排第一列,0-3 = -3,绝对值小于4.
全代码展示:
# include <iostream>
# include <vector>
using namespace std;
const int N = 4;
int arr[N][N];
// 定义对角线,写对角线以及列.
bool dg[N * 2], udg[N * 2], col[N];
void dfs(int cur) {
if (cur == N) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
cout << endl;
return;
}
for (int i = 0; i < N; i++) {
if (!col[i] && !dg[i + cur] && !udg[i - cur + N]) {
arr[cur][i] = 1;
col[i] = dg[i + cur] = udg[i - cur + N] = true;
dfs(cur + 1);
arr[cur][i] = 0;
col[i] = dg[i + cur] = udg[i - cur + N] = false;
}
}
}
int main() {
for (int i = 0; i < N;i++) {
for (int j = 0;j<N; j++) {
arr[i][j] = 0;
}
}
dfs(0);
return 0;
}