n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
思路:
刚开始的思路是,用一个二维int数组来保存,后来发现很繁琐,其次就是需要返回的是一个vector<vector<string>>那么我们就需要add一个vector<string>进去,所以我们就必须填满每一个vector<string>,再在这个基础上进行修改,最合适和最方便。
vector<string> v(n,string(n,'.'));
在这个基础上修改,再递归到下一层则保存下来即可。
- 第一点就是,八皇后每行每列不能存在多于自己同列同行的。这里就i++,把列固定。反之,行也是。
- 第二点每个对角线和反对角线,相减都是同一个常数。
bool entarck(vector<string>& v,int row,int col){
bool valid=true;
for(int i=0; valid && i<row; valid=v[i++][col]!='Q');
for(int i=0; valid && i<col; valid=v[row][i++]!='Q');
for(int i=row, j=col; valid && i-- && j--; valid=v[i][j]!='Q');
for(int i=row, j=col; valid && i-- && ++j<v.size(); valid=v[i][j]!='Q');
return valid;
}
其次就是,什么时候探索?,什么时候回溯?。从那里开始探索?,回溯之后怎么办?。
当第一次调用add函数,就是从0开始探索。
什么时候回溯?当判断,当前的点i,j调用entarck函数判断,不成立,这个时候就进行回溯。
回溯之后怎么办?首先把当前的置Q擦除,即重新置. 这个时候就会回溯到上一层,上一层就会跳到下一个点。
同时,思路一定是,先置Q,再判断。再回溯.
附上代码:
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> res;
//构造出二维状态数组
//vector<vector<int>> index(n,vector<int>(n));
//初始化的一组点
vector<string> v(n,string(n,'.'));
add(res,0,v);
return res;
}
void add(vector<vector<string>>& res,int start,vector<string>& v){
if(v.size()==start){
res.push_back(v);
return;
}
for(int i = 0;i<v.size();i++){
v[start][i] = 'Q';
//对应每一列,往里加q
if(entarck(v,start,i)){
add(res,start+1,v);
}
//回溯
v[start][i] = '.';
//需要删除吗?
//好像不需要删除
}
}
//判断同行同列对角行啊
bool entarck(vector<string>& v,int row,int col){
bool valid=true;
for(int i=0; valid && i<row; valid=v[i++][col]!='Q');
for(int i=0; valid && i<col; valid=v[row][i++]!='Q');
for(int i=row, j=col; valid && i-- && j--; valid=v[i][j]!='Q');
for(int i=row, j=col; valid && i-- && ++j<v.size(); valid=v[i][j]!='Q');
return valid;
}
};