题目:The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q'
and '.'
both indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[ [".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", // Solution 2 "Q...", "...Q", ".Q.."] ]
思路:回溯或者二进制法
思路很清晰,首先我是每行插入一个,所以行的问题不需要考虑,然后就是需要判断列和两个对角线的问题。判断的程序是一个难题:主要就是八个位判断
1<<colIndex 代表第几列的时候,向左移位colIndex位,如果有效(此时为0),此时就要setFlag,并操作,因为,我刚刚就是已经有代表哪几个位已经占据的标志了。至于后面的unsetFlag函数,只是通过某种数学逻辑关系进行运算,返回原来的状态。colFlag&~(1<<colIndex)。
在真正的主程序里面,首先定义rowIndex为answer的数组,一旦满了,就保存进堆栈。因为最大只能到n-1的。
首先在answer放入n个’.',然后从0到n-1 开始遍历,先是判断是否满足,不满足直接return,满足,开始更新各个flag值,此时answer已经存入一组数,满足了,可以存入堆栈,然后开始下一层,这个时候,还是从0开始一个个判断,发现,总有不能满足的。继续下一个i值。
值得注意的是,每个循环里面,在加入q之后,为了下一列的判断,还得出栈,退出q,不然程序出错。
answer的进栈和出栈也是对称的。总之,回溯法是对称的。
代码:
class Solution {
private:
int colFlag;//代表列
int diagFlag1;//index=i+j
int diagFlag2;//index=n-1+i-j
bool isValid(int rowIndex,int colIndex,int n){
//行不需要判断,因为我是按照行走的
//为0说明有效
if( (1<<colIndex)&colFlag ){
//为1 无效
return false;
}
if( (1<<(rowIndex+colIndex))&diagFlag1 ){
return false;
}
if( (1<<(n-1+rowIndex-colIndex) ) & diagFlag2 ){
return false;
}
return true;
}
void setFlag(int rowIndex,int colIndex,int n){
colFlag |=(1<<colIndex);
diagFlag1 |=(1<<(rowIndex+colIndex));
diagFlag2 |=(1<<(n-1+rowIndex-colIndex));
}
void unsetFlag(int rowIndex, int colIndex, int n) {
colFlag &= ~(1 << colIndex);
diagFlag1 &= ~(1 << (rowIndex + colIndex));
diagFlag2 &= ~(1 << (n + rowIndex - colIndex - 1));
}
void queenHelper(int n, vector<string> &answer, vector<vector<string> > &result) {
int rowIndex = answer.size();
if (rowIndex == n) {
result.push_back(answer);
return;
}
answer.push_back(string(n, '.'));
for (int i = 0; i < n; i++) {
if (isValid(rowIndex, i, n)) {
setFlag(rowIndex, i, n);
answer.back()[i] = 'Q';
queenHelper(n, answer, result);
answer.back()[i] = '.';
unsetFlag(rowIndex, i, n);
}
}
answer.pop_back();
}
public:
vector<vector<string> > solveNQueens(int n) {
// https://oj.leetcode.com/problems/n-queens/
colFlag = diagFlag1 = diagFlag2 = 0;
vector<vector<string> > result;
vector<string> answer;
queenHelper(n, answer, result);
return result;
}
};