题目描述
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
样例输入
示例 1:
输入:n = 4 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] 解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1 输出:[["Q"]]
提示:
1 <= n <= 9
题解
约束条件
- 不能同行
- 不能同列
- 不能同斜线
核心思想:
使用回溯法尝试遍历所有位置,其中for循环控制棋盘的列,递归深度控制棋盘的行。
由上图可以看到,回溯法中构造的树的高度就是矩阵的高,for循环控制矩阵的宽,也就是树宽,只要我们搜索到了树的叶子节点,说明就找到了皇后们的合理位置了。
故而使用回溯法时,尝试对每个位置都放置一个皇后,当然放置之前要首先判断该位置是否“合法”,假如我们能够走到叶子结点,说明找到了一个可行方案,收集即可
代码
class Solution {
private:
vector<vector<string>> res;
//判断当前遍历到的位置是否合法
bool isValid(int row,int col,vector<string>& chessbord,int n)
{
//检查列
for(int i=0;i<row;i++)
{
if(chessbord[i][col]=='Q')
return false;
}
//检查左上角
for(int i=row-1,j=col-1;i>=0 && j>=0;i--,j--)
{
if(chessbord[i][j]=='Q')
return false;
}
//检查右上角
for(int i=row-1,j=col+1;i>=0 && j<n;i--,j++)
{
if(chessbord[i][j]=='Q')
return false;
}
return true;
}
public:
void backing(int& n,int row,vector<string>& chessbord)
{
if(row==n)
{
res.push_back(chessbord);
return ;
}
//for循环控制列
for(int col=0;col<n;col++)
{
//判断当前是否“合法”,如果合法才能放置“皇后”
if(isValid(row,col,chessbord,n))
{
chessbord[row][col]='Q';
backing(n,row+1,chessbord);//递归控制行
chessbord[row][col]='.';
}
}
}
vector<vector<string>> solveNQueens(int n) {
vector<string> chessbord(n,string(n,'.'));
backing(n,0,chessbord);
return res;
}
};