优质博客
问题描述
N 皇后问题是指在 n x n
的棋盘上放置 n
个皇后,使得每个皇后都不能互相攻击。皇后可以在同一行、同一列、同一对角线上攻击其他皇后。因此,问题的核心是如何安排皇后的位置,保证没有两个皇后互相攻击。
核心思路
-
初始化棋盘与标记数组:创建一个
n x n
的棋盘,并使用三个布尔数组row
,dg
,udg
分别记录每列、主对角线、副对角线上是否已有皇后。 -
递归搜索与回溯:
- 从第 0 行开始,依次为每一行寻找合适的列(即没有皇后攻击的位置)。
- 每次找到合法位置后,将其标记为已放置皇后,递归地处理下一行。
- 如果递归到第
n
行,说明找到了一组可行解,打印当前棋盘。 - 如果当前行所有列都不满足条件,则回溯到上一行,撤销上一个皇后的放置,并尝试其他位置。
-
剪枝:
- 使用布尔数组
row
,dg
,udg
,有效地剪枝,减少不必要的搜索。
- 使用布尔数组
全局变量定义
const int N=20;
char g[N][N]; // 用于存储棋盘,'Q' 表示皇后,'.' 表示空位
bool row[N],dg[N],udg[N]; // 分别记录列、主对角线、副对角线是否已经有皇后
int n; // 棋盘大小
g[N][N]
:棋盘,用于表示皇后和空格。g[i][j] = 'Q'
:第i
行第j
列放置了一个皇后。g[i][j] = '.'
:当前位置没有皇后。
row[N]
:用于记录每一列是否已有皇后,防止同列放置两个皇后。dg[N]
和udg[N]
:分别用于记录主对角线和副对角线是否有皇后。- 主对角线:对角线元素满足
i - j
相同。 - 副对角线:对角线元素满足
i + j
相同(截距b看做第几行,最后加n是为了防止溢出)。
- 主对角线:对角线元素满足
DFS函数实现
void dfs(int u) {
if (u == n) { // 如果 u == n,说明已经成功放置 n 个皇后,找到一个解
for (int i = 0; i < n; i++) puts(g[i]); // 输出当前解法
puts(""); // 输出空行用于分隔
return;
}
int x = u; // x 代表当前正在处理的行
for (int y = 0; y < n; y++) { // 枚举当前行的每一列 y
if (!row[y] && !dg[y - x + n] && !udg[y + x]) { // 如果 y 列、主对角线、副对角线都没有皇后
g[x][y] = 'Q'; // 在 (x, y) 处放置皇后
row[y] = dg[y - x + n] = udg[y + x] = true; // 标记列、主对角线、副对角线
dfs(u + 1); // 递归处理下一行
g[x][y] = '.'; // 回溯:撤销在 (x, y) 处的皇后
row[y] = dg[y - x + n] = udg[y + x] = false; // 恢复状态
}
}
}
回溯操作:如果当前行皇后放置成功,继续处理下一行;如果失败,则撤销当前放置的皇后,并尝试下一个位置。通过这种回溯方式,能够找到所有可能的解法。
主函数
int main() {
cin >> n; // 读取棋盘大小
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
g[i][j] = '.'; // 初始化棋盘为空位
}
}
dfs(0); // 从第 0 行开始搜索
return 0;
}
- 初始化棋盘:将棋盘的每个位置初始化为
'.'
,表示空位。 - 调用
dfs(0)
:从第 0 行开始,尝试放置皇后并找到所有解。
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=20;
char g[N][N];
bool row[N],dg[N],udg[N];
int n;
void dfs(int u){
if(u==n)//已经找到一组解
{
for(int i=0;i<n;i++) puts(g[i]);
puts("");
return;
}
//枚举u这一行,搜索合法的列
int x=u;
for(int y=0;y<n;y++)
{
if(!row[y]&&!dg[y-x+n]&&!udg[y+x])
{
g[x][y]='Q';
row[y]=dg[y-x+n]=udg[y+x]=true;
dfs(u+1);
g[x][y]='.';
row[y]=dg[y-x+n]=udg[y+x]=false;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
g[i][j]='.';
}
}
dfs(0);
return 0;
}