Leetcode 51.N皇后
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:

核心思路:
dfs深搜 关键在于三个约束条件如何记录:行row 列col 斜线dg与udg
- 行row:枚举每一行即可
- 列col:用数组
vector<bool> col判断是否枚举到 - 至于斜线dg和udg则是重点解决问题
如图,两条黑(主斜线dg)格子坐标相减为定值即x-y=c 两条红(副斜线)格子坐标相加为定值即x+y=c
在主斜线上我们得出结论:在主斜线dg上,如果坐标满足x-y=c(定值)上,则这些所有坐标在同一斜线上。如图 x-y = 0 的坐标在同一斜线上,x-y = -1的坐标也在同一斜线上(仍是主斜线 只是平行)
同理:在两条红(副斜线udg)上,坐标相加为定值即x+y=c也在同一斜线上。
代码块
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> result;
vector<bool> dg(2 * n); // 对角线数组的大小应该是2n
vector<bool> udg(2 * n); // 反对角线数组的大小也应该是2n
vector<bool> col(n); // 列数组的大小是n
vector<string> board(n, string(n, '.')); // 初始化棋盘
dfs(0, n, result, dg, udg, board, col);
return result;
}
private:
void dfs(int u, int n, vector<vector<string>>& result, vector<bool>& dg, vector<bool>& udg, vector<string>& board, vector<bool>& col) {
if (u == n) {
result.push_back(board); // 将完整棋盘添加到结果中
return;
}
for (int y = 0; y < n; y++) {
int x = u; // 这里x是固定的,因为我们正在放置第u行的皇后
int dx = y - x + n; // 转换为非负索引
int ud = x + y; // 副对角线索引
if (!col[y] && !dg[dx] && !udg[ud]) {
col[y] = dg[dx] = udg[ud] = true;
board[x][y] = 'Q';
dfs(u + 1, n, result, dg, udg, board, col);
board[x][y] = '.'; //恢复现场
col[y] = dg[dx] = udg[ud] = false;
}
}
}
};
细节补充
-
因为x-y=c为负值,故我们给x-y加上一个偏移量n使得x-y>0(数组索引没有负数),当然,偏移量可任选,只要满足x-y>0即可。
-
至于dg和udg数组开2n空间是因为对角线有2n-1条。
-
if (!col[y] && !dg[dx] && !udg[ud])不同列 不同主对角 不同副对角。 -
至于函数参数太多,应该可以采用开全局变量优化,有能力可以试试。