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

输入 :n = 4
输出 :[[".Q...","...Q","Q...","...Q."],["...Q.","Q...","...Q",".Q..."]]
解释 :如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入 :n = 1
输出 :[["Q"]]
提示:
1 <= n <= 9
思路
1 进行dfs,每层代表选取的行数,层内只需要遍历列数。
2 每个位置需要判断列、主对角线、副对角线是否重复,行不需要判断,因为dfs将层隔开了。
3 主对角线和副对角线的表示可以用 x + y 和 y - x 表示,注意y - x可能是负数,所以需要进行偏正为y - x + n。
代码
cpp
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
// 记录多个答案
vector<vector<string>>ans;
// 记录单个答案
vector<string>res;
// 记录每层的答案
string s(n, '.');
// 某一列是否被标记
vector<bool> st_col(n, false);
// 主对角线是否被标记
vector<bool> main_diag(n * 2, false);
// 次对角线是否被标记
vector<bool> sub_diag(n * 2, false);
// 每层枚举一行的所有列
dfs(0, n, st_col, main_diag, sub_diag, s, res, ans);
return ans;
}
void dfs(int row, int n, vector<bool> &st_col, vector<bool> &main_diag, vector<bool> &sub_diag, string &s, vector<string>&res, vector<vector<string>> &ans)
{
if(res.size() == n)
{
ans.push_back(res);
return;
}
// 每层枚举一行的所有列
for(int col = 0; col < n; ++col)
{
// 没有列、主副对角线冲突
if(st_col[col] == false && main_diag[row + col] == false && sub_diag[col - row + n] == false)
{
st_col[col] = true;
main_diag[row + col] = true;
sub_diag[col - row + n] = true;
s[col] = 'Q';
res.push_back(s);
s[col] = '.'; // 提前复原, 下一层要用到
dfs(row + 1, n, st_col, main_diag, sub_diag, s, res, ans);
st_col[col] = false;
main_diag[row + col] = false;
sub_diag[col - row + n] = false;
res.pop_back();
}
}
}
};