题意
在n*n的棋盘上,放上n个皇后,两个皇后不可以放在同一行、同一列、同一正对角线和同一副对角线。
给一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
分析
每进入一行,遍历这一行的所有位置,每遍历到新的位置,检查这个位置所在的列、主对角线和副对角线是否三者都
没有放皇后,如果满足,则在当前位置尝试放皇后,进入下一行;如果不满足,继续往右遍历。
1.每次都是一行一行的放皇后,因此可以认为在当前行放皇后时,上面的每一行都已经了放了一个皇后,
所以不需要数组来记录状态。
2.使用数组col来记录每一列是否放置了皇后。
3.分别使用数组dg和udg来记录每条对角线和每条副对角线上是否放置了皇后。
设列的索引为y,行的索引为x,则正对角线可以表示为y=x+k,k为直线的截距,不同的直线有不同的截距k,
而副对角线可以表示为y=-x+b,同样,b为直线的截距。
则每条正对角线可以使用截距k来区分,即 k=y-x ;
条副对角线也可以使用截距来区分,即 b=y+x 。
需要注意的是,k=y-x有可能是负数,而数组的索引是不能为负的。
Attention:此题是需要回溯的,因此要恢复现场。
代码
class Solution {
public:
int n;
vector<vector<string>> ans;//用于存储放置了n个皇后的棋盘状态
vector<string> t;//用于存储当前棋盘的状态
//col用于记录每一列放置皇后的状态,dg用于记录每一条正对角线放置皇后的状态,udg用于记录每一条副对角线放置皇后的状态
vector<int> col, dg, udg;
vector<vector<string>> solveNQueens(int n1) {
n = n1;
t = vector<string>(n, string(n, '.'));//初始化棋盘
col = vector<int> (n);
dg = udg = vector<int> (2 * n);
dfs(0);//从索引为0的行开始遍历
return ans;
}
//暴力搜索
void dfs(int u) {
//如果u等于n,则说明索引0到u-1的行都遍历过了,可以直接返回答案
if (u == n) {
ans.push_back(t);
return;
}
for (int i = 0; i < n; i++) {
//只有当前位置所在的行、列、正对角线以及副对角线都没有皇后,才可以尝试放置皇后
if (!col[i] && !dg[i - u + n] && !udg[i + u]) {
col[i] = dg[i - u + n] = udg[i + u] = 1;
t[u][i] = 'Q';//在当前位置放皇后
//在当前位置放了皇后,即这一行就有皇后了,去下一行尝试放皇后
dfs(u + 1);
//恢复现场
col[i] = dg[i - u + n] = udg[i + u] = 0;
t[u][i] = '.';
}
}
}
};