N queens puzzle
Math solution
The solution is not unique, this method provide only one of them.
DFS
用四个数组记录位置可选的状态,每填一个点,其所导致失效的行、列、两个对角线必定是独一无二的,这样就方便在DFS中还原可选状态,比记录点[row][col]更好,因为同一点可能因多个点的填入被设为无效。
- 对角线 \ :
row - col = -(n-1) ~ n-1
为便于数组处理,整体向右偏移n-1,则row - col + n-1 = 0 ~ 2n-2
- 对角线 / :
row + col = 0 ~ 2n-2
若逐行填入queen,那么row是否有效可选不必记录;同理,若逐列填写,那么col不必记录。
class Solution {
public:
int N;
vector<bool> col, ddiag, udiag;
vector<string> temp;
vector<vector<string>> ans;
vector<vector<string>> solveNQueens(int n) {
N = n;
col.resize(n, 1);
ddiag.resize(2*n-1, 1);
udiag.resize(2*n-1, 1);
for(int c=0; c<n; c++) DFS(0, c);
return ans;
}
//put queen at [r][c]
void DFS(int r, int c){
//put queen
string s(N, '.');
s[c] = 'Q';
temp.emplace_back(s);
//recursion exit
if(r==N-1){
ans.emplace_back(temp);
temp.pop_back();
return;
}
//reduce options
col[c] = false;
ddiag[r-c+N-1] = false;
udiag[r+c] = false;
//check [r+1][...]
for(int i=0; i<N; i++){
if(col[i] && ddiag[r-i+N] && udiag[r+1+i]){
DFS(r+1, i);
}
}
//roll back
col[c] = true;
ddiag[r-c+N-1] = true;
udiag[r+c] = true;
temp.pop_back();
return;
}
};