n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,
该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例
由题目的意思我们可以知道皇后与皇后之间不可能在同一行或者同一列。所以每一行肯定有一个且只有一个皇后。所有皇后的状态数有 8!种,再结合其他的条件来选择合适的状态。由此很明显想到了回溯法。虽然有点暴力但是AC啦。下面上AC的代码:
bool isok(int row,int a[]){ //判断第row行的col列(a[row])是否可以放皇后
for(int i=0;i<row;i++) //col列符合条件返回true,否则返回false
if(a[i]==a[row]||fabs(a[row]-a[i])==(row-i))
return false; //数组 a[]是存储每一行放皇后的col列位置
return true; //a[0]表示第0行皇后位置,a[n-1]代表第n-1行皇后位置
}
void queen(int row,int n,vector<vector<string> > &ss,vector<string> &s,string s1,int a[]){ // 递归回溯法
if(row==n) //若row==n,意味前面已经放置好n个皇后了,此时的 s代表一种皇后摆法
{
ss.push_back(s); //把s 导入ss 中
s.pop_back(); //把最后一行的元素再取出来,判断有没有其他成功的可能
}
else{ //若row!=n,不断的递归寻找
int col; //列
for(col=0;col!=n;col++){
a[row]=col; //假设第row行放皇后位置为col
if(isok(row,a)){ //判断皇后是否可以放置这个 col,不能就什么也不做,col++
s1[a[row]]='Q'; //否则再深一层的进去寻找下一行的皇后位置
s.push_back(s1); //把该行可以放皇后的col记录进 s中
s1[a[row]]='.'; //string仍然变回初始状态
queen(row+1,n,ss,s,s1,a); //寻找下一行的皇后 col
}
}
if(row==0&&col==n); //当row==0,col==n时意味着遍历全部结束,不需要做任何的操作。
//PS:刚开始漏了这个判断,程序一直崩溃。找了好久bug终于发现这里有问题。
else
s.pop_back(); //如果这一行找不到皇后的位置,意味着上一行放皇后的位置不正确,删除上次进入 s的记录
}
}
class Solution {
public:
vector<vector<string> > solveNQueens(int n) {
vector<vector<string> > ss;
vector<string> s;
string s1="";
int a[n];
for(int i=0;i<n;i++) //先把一行全部的str变为为全' . '
s1=s1+".";
queen(0,n,ss,s,s1,a);
return ss;
}
};
static auto _=[]()
{
ios::sync_with_stdio(false);
cin.tie(0);
return 0;
}();
PS:因为当时漏判断一个条件,导致空的vector可以再次pop_back() , 因此程序崩溃 ,找了一段时间才发现原因,补上判断条件就AC了。
如果代码有什么错误,欢迎大家指出!