题目:
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例 1:
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
来源:
2题一样,相同代码提交即可。
解题思路:回溯
定义一个path,记录每行中皇后的列位置,path[i]表示第i行的皇后所在的列号。
- 结果满足条件:放置的皇后数量等于n时,输出并退出。
- 递归调用条件:检查当前节点是否与之前有冲突,如果没有,则继续递归。
- 检查当前位置能否放置皇后:一行一个皇后,所以行上不冲突,不用检查。只需检查列、对角线、反对角线是否已放置。
如下图,绿色对角线上行号、列号的关系:行号-列号是相同的;橙色对角线行号、列号关系:行号+列号是相同的。冲突检查参见代码中check()函数。
class Solution {
public:
vector< vector<string> > result;
vector<int> path; // path[i]:第i行皇后放置的位置
vector< vector<string> > solveNQueens(int n) {
back(n, 0);
return result;
}
// 放置第k个皇后,k从0开始
void back(int n, int k) {
if (k == n) {
out();
return;
}
// 找到可以放置的列
for (int i = 0; i < n; i++) {
if (check(i)) {
path.push_back(i);
back(n, k+1);
path.pop_back();
}
}
}
// 检查第path.size()行,第p列是否合法
bool check(int p) {
int d1 = p - path.size(); // 列号-行号
int d2 = p + path.size(); // 列号+行号
for (int i = 0; i < path.size(); i++) {
if (path[i] == p || // 列
d1 == path[i] - i || // 左上-右下
d2 == path[i] + i) { // 右上-左下
return false;
}
}
return true;
}
void out() {
vector<string> ret;
int n = path.size();
for (int i = 0; i < n; i++) {
string t(n, '.');
t[path[i]] = 'Q';
ret.push_back(t);
}
result.push_back(ret);
}
};