题目描述如下:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例:
输入: 4
输出:
[[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]]
解释: 4 皇后问题存在两个不同的解法。
思路分析:
按照规则,两个皇后不能在同一列,同一行,同一个对角线上,这个问题可以使用回溯解决,但是需要明白回溯的重点,是每一行的状态,设pow初值为零,在选定了第一行的皇后'位置之后,我们肯定是要在第二行找一个合适的位置,把第二个皇后安排上,然后依次下去,直到所有的皇后被安排完毕。所以递归的终止条件 就是pow=n(从0开始,到n则前n-1行安排完毕,这是为了结合后面的程序),而选择条件就是两个皇后不可以出现在同一列,同一行,同一对角线,由于对角线上的点可以表示为(pow+i,col+i),(pow-i,col+i),(pow+i,col-i),(pow-i,col-i),考虑到我们的安排顺序是从上往下,所以下面没有数据,也就可以忽略,所以可以使用下面的代码判断是否符合条件
bool isok(vector<string>& cur,int row,int col)
{
for(int i=0;i<cur.size();i++)
if(cur[i][col]=='Q')
return false;
for(int i=row,j=col;i>=0&&j>=0;i--,j--)
if(cur[i][j]=='Q')
return false;
for(int i=row,j=col;i>=0&&j<cur.size();i--,j++)
if(cur[i][j]=='Q')
return false;
return true;
}
其中cur用于盛放当前解,cur.size()就是n
确定了选择条件和终止条件之后我们可以按照回溯的一般套路去写代码了。
AC代码如下:
编程语言c++:
class Solution {
public:
bool isok(vector<string>& cur,int row,int col)//用于判断是否符合条件
{
for(int i=0;i<cur.size();i++)
if(cur[i][col]=='Q')
return false;
for(int i=row,j=col;i>=0&&j>=0;i--,j--)
if(cur[i][j]=='Q')
return false;
for(int i=row,j=col;i>=0&&j<cur.size();i--,j++)
if(cur[i][j]=='Q')
return false;
return true;
}
void prem (vector<vector<string>>& res,vector<string> &cur,int row,int n)//递归函数
{
if(row==n)//如果row为n代表前n行都已经安排完毕,解已经得到,可以终止了
res.push_back(cur);
for(int i=0;i<n;i++)//遍历每行中的每一个元素
{
if(isok(cur,row,i))//达成条件就设为Q
{
cur[row][i]='Q';
prem(res,cur,row+1,n);//继续寻找下一行符合条件的位置
cur[row][i]='.';//下面找不到解,那就恢复状态,继续尝试
}
}
}
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> res;
vector<string> cur(n,string(n,'.'));
prem(res,cur,0,n);
return res;
}
};