51. N皇后
问题
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
分析
正常dfs回溯即可,难度不如131分割回文串。子问题是当前行的棋子放在哪一列,需记录哪一列不能放,包括列和两个对角线原因。对角线需要转化,左上到右下用x-y为定值;右上到左下用x+y为定值,可用map或者set存储这些定值,需要判断是否可放时find或count即可。
代码
class Solution {
public:
vector<vector<string> > res;
int n;
int st_col[10];
unordered_map<int, int> lr; // top-left to bottom-right
unordered_map<int, int> rl;
void dfs(vector<string> v_s, int x) { // x row
if (x == n) {
res.push_back(v_s);
return ;
}
for (int i = 0; i < n; i++) {
if (st_col[i]) {continue;}
if (lr.find(x-i) != lr.end()) {continue;}
if (rl.find(x+i) != rl.end()) {continue;}
v_s[x][i] = 'Q';
st_col[i] = 1;
lr.insert(make_pair(x-i, 1));
rl.insert(make_pair(x+i, 1));
dfs(v_s, x+1);
v_s[x][i] = '.';
st_col[i] = 0;
lr.erase(x-i);
rl.erase(x+i);
}
}
vector<vector<string>> solveNQueens(int n) {
this->n = n;
vector<string> v_s(n, string(n, '.'));
dfs(v_s, 0);
return res;
}
};
new
时隔很久,我还是能写出n皇后,开心。但是要注意diffst中x-i可能为负,所以整体加偏移+n。
当然,用哈希的话,就可以直接存负了。
class Solution {
private:
int cst[12];
vector<vector<string>> res;
int n;
int sumst[22], diffst[22];
void dfs(int x, vector<string> t) {
if (x >= n) {
res.push_back(t); return ;
}
string s(n, '.');
for (int i = 0; i < n; i++) { // col
if (cst[i]) {continue;}
if (sumst[x+i]) {continue;}
if (diffst[x-i+n]) {continue;}
s[i] = 'Q';
cst[i] = 1; sumst[x+i] = 1; diffst[x-i+n] = 1;
t.push_back(s);
dfs(x+1, t);
t.pop_back();
s[i] = '.';
cst[i] = 0; sumst[x+i] = 0; diffst[x-i+n] = 0;
}
}
public:
vector<vector<string>> solveNQueens(int n) {
memset(cst, 0, sizeof cst);
memset(sumst, 0, sizeof sumst);
memset(diffst, 0, sizeof diffst);
this->n = n;
dfs(0, {});
return res;
}
};

浙公网安备 33010602011771号