题解
class Solution {
public:
int totalNQueens(int n) {
int ans = 0;
vector<int> queens(n);
vector<int> col(n), diag1(2 *n-1), diag2(2*n - 1);
auto dfs = [&](auto && dfs, int r){
if (r == n)
{
ans ++;
return;
}
for(int c = 0 ; c < n; c ++)
{
int d2 = r - c + n - 1;
if (!col[c] && !diag1[r + c] && ! diag2[d2])
{
queens[r] = c;
col[c] = diag1[r + c] = diag2[d2] = true;
dfs(dfs, r+1);
col[c] = diag1[r + c] = diag2[d2] = false;
}
}
};
dfs(dfs, 0);
return ans;
}
};
思路
这是一个典型的回溯思想的题
DFS
首先需要确立一个dfs遍历目标,需要知道的是选择位置,其实就是不同行上的皇后位置的全排列,代码中记为queens数组,queens[r] = c表示第r行上皇后的位置是c。
所以在这个基础上,我们只需要知道不能放的位置是什么。对此,需要三个数组,col[i]==true表示第i列上已经有皇后了,diag1是皇后的行列之和即r+c,diag2是皇后的行列之差r-c(为了方便数组索引,不让计算结果为负,所以需要+(n-1))。
col容易理解,但是,diag1和diag2怎么理解呢?其实画图就可以发现,如果两个位置(r1,c1)和(r2,c2)在斜方向上冲突,则r1+c1 == r2+c2或者r1-c1 == r2-c2,这一点本质上可以通过向量来推导出,即两点连线的向量与两个斜单位向量之一垂直。
有了这些接下来就简单了,只需要dfs遍历判断并且回溯。