N皇后问题解法(回溯算法)
这段代码使用深度优先搜索(DFS)和回溯算法来解决经典的N皇后问题。下面是对代码的详细解析:
问题描述
在n×n的棋盘上放置n个皇后,使得它们互不攻击(即不在同一行、同一列或同一对角线上)。
代码解析
全局变量
const int N = 10;
bool col[N], dg[2*N], ndg[2*N]; // 标记数组
int n; // 棋盘大小
char g[N][N]; // 棋盘表示
col[i]: 标记第i列是否有皇后dg[r-i+n]: 标记左上到右下的对角线(主对角线方向)ndg[r+i]: 标记左下到右上的对角线(副对角线方向)g[N][N]: 二维字符数组表示棋盘,‘Q’表示皇后,’.'表示空位
DFS函数
void dfs(int r) // r表示当前处理的行
{
if(r == n) // 找到一个解
{
// 打印棋盘
for(int i = 0; i < n; i++) cout << g[i] << endl;
cout << endl;
return;
}
for(int i = 0; i < n; i++) // 尝试在当前行的每一列放置皇后
{
// 检查列和对角线是否可用
if(!col[i] && !dg[r-i+n] && !ndg[r+i])
{
// 放置皇后并标记
col[i] = dg[r-i+n] = ndg[r+i] = true;
g[r][i] = 'Q';
// 递归处理下一行
dfs(r+1);
// 回溯,撤销选择
g[r][i] = '.';
col[i] = dg[r-i+n] = ndg[r+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); // 从第0行开始搜索
return 0;
}
算法特点
- 行优先搜索:逐行放置皇后,确保每行只有一个皇后
- 冲突检测:
col[i]检测列冲突dg[r-i+n]检测主对角线冲突ndg[r+i]检测副对角线冲突
- 回溯机制:当无法继续放置时撤销选择,尝试其他可能性
对角线索引技巧
-
主对角线(左上到右下):
- 使用
r-i+n作为索引(加n避免负索引) - 同一条对角线上
r-i为常数
- 使用
-
副对角线(左下到右上):
- 使用
r+i作为索引 - 同一条对角线上
r+i为常数
- 使用
复杂度分析
- 时间复杂度:O(n!),因为最坏情况下需要尝试所有排列组合
- 空间复杂度:O(n),主要消耗在递归栈和标记数组上
示例输出(n=4时)
.Q..
...Q
Q...
..Q.
..Q.
Q...
...Q
.Q..
这段代码是解决N皇后问题的经典回溯实现,通过巧妙的标记数组和递归回溯,高效地找到了所有可能的解。
736

被折叠的 条评论
为什么被折叠?



