回溯算法----N皇后问题
回溯算法一直都困扰我很长一段时间,看了回溯算法的视频,特地来写一下这个算法,加深印象。
回溯算法的通式
回溯算法有个通式。
void backtrack(){
if(判断是否到头了){
添加到vector里(一次正确的回溯结束,进行存储操作)
return;
}
for(){
...
存储元素;
backtrack;
删除元素;
}
}
当然这样写现在看不懂,往下看看回溯代码块就差不多了。
N皇后问题
N皇后问题指一个棋盘中,皇后Q所在的一行、一列、左斜线、右斜线都没有其他的皇后Q,这样组成的棋盘。具体题目可见leetcode51:
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例 1:
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] 解释:如上图所示,4 皇后问题存在两个不同的解法。
来源:力扣(LeetCode) 链接:力扣
解法
首先创造一个公共的vector容器,来存储答案。(个人习惯,也可以在backtrack中添加一个参数一直将res传递)
vector<vector<string>> ans;
然后创建一个棋盘:
vector<string> board(n,string(n,'.'));
回溯函数:
void backtrack(vector<string>& board, int row){
if(row == board.size()){
ans.emplace_back(board);//一次回溯完成
return;
}
for(int col = 0;col < board.size();col++){
if(!isValid(board,row,col)){
continue;
}
board[row][col] = 'Q';//存储元素
backtrack(board,row+1);
board[row][col] ='.';//删除元素
}
}
参数:
board是棋盘,需要对它进行操作,也是要传送到ans的vector。row是行,每次递归都需要将行数加1。
参数根据代码而定,本人也很难搞清究竟哪些来作为向下传递的参数。所以就哪些参数需要就传哪些。。。
存储与删除元素:
这里是存储与删除,其实笼统说是一直修改board,然后做完一整个回溯后,返回来对board维护,让board完好如初。
isValid是检查函数,由于是按行从上而下放置皇后Q的,所以,行不用检查,当前位置向下的列和斜线都不用检查。最终只需要检查上列,左上,右上。
bool isValid(vector<string>& board,int row,int col){
for(int i = 0;i < row;i++){
if(board[i][col] == 'Q')//检查列
return 0;
if(col-row+i>=0){//检查左上
if(board[i][col - row + i] == 'Q')
return 0;
}
if(col+row-i<board.size()){//检查右上
if(board[i][col + row - i] == 'Q')
return 0;
}
}
return 1;
}
完整代码:
class Solution {
public:
vector<vector<string>> ans;
bool isValid(vector<string>& board,int row,int col){
//检查列
for(int i = 0;i < row;i++){
if(board[i][col] == 'Q')
return 0;
if(col-row+i>=0){
if(board[i][col - row + i] == 'Q')
return 0;
}
if(col+row-i<board.size()){
if(board[i][col + row - i] == 'Q')
return 0;
}
}
return 1;
}
void backtrack(vector<string>& board, int row){
if(row == board.size()){
ans.emplace_back(board);
return;
}
for(int col=0;col<board.size();col++){
if(!isValid(board,row,col)){
continue;
}
board[row][col] = 'Q';
backtrack(board,row+1);
board[row][col] ='.';
}
}
vector<vector<string>> solveNQueens(int n) {
vector<string> board(n,string(n,'.'));
backtrack(board,0);
return ans;
}
};