Nクイーンパズル
数学の解
解決策はユニークではありません、この方法はそれらのうちの1つだけを提供します。
DFS
4つの配列を使用して、位置のオプションの状態を記録します。入力された各ポイントについて、障害の原因となる行、列、および2つの対角線は一意である必要があるため、DFSでオプションの状態を復元すると便利です。複数のポイントが原因で同じポイントが無効になる可能性があるため、レコードポイント[row] [col]よりも便利です。
- 対角線\:
row - col = -(n-1) ~ n-1
配列処理を容易にするために、全体がn-1だけ右にオフセットされ、次にrow - col + n-1 = 0 ~ 2n-2
- 対角/:
row + col = 0 ~ 2n-2
クイーンを行ごとに入力する場合は、行が有効かどうかを記録する必要はありません。同様に、列ごとに入力する場合は、列を記録する必要はありません。
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;
}
};