N-Queens
问题描述:https://leetcode.com/problems/n-queens/
在学习回溯的时候,八皇后问题是一道非常有名的问题,八皇后的问题的描述是:在一个8*8的棋盘上放置8个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击)。
当将问题扩展之后就变成了N皇后的问题。
题目给你一个数字N,让你返回满足条件的棋盘格局。
这道题主要是要想好回溯变量和是否回溯的条件以及结束回溯的条件。题目要求返回棋盘格局,所以我们可以一行一行的来进行回溯,所以回溯变量可以确定为行数。当我们回溯到最后一行的时候,可以确定我们已经得到了一个答案,所以可以结束回溯,返回。是否回溯的条件,也就是判断是否需要剪枝,当我们判断如果在某一行某一列放置皇后会引起攻击,拿着一个位置就不能放,剪枝。
如何判断皇后会引起攻击呢:
1 在同一行,我们是按行来进行回溯的,不存在这个问题
2 按列,我们可以用一个数组存储已经放置皇后的列,然后每次判断一个位置可以判断该列是否在数组中
3 按对角线,两个皇后在对角线上的条件是|rows1-rows2|=|cols1-cols2|,我们是按照行,进行回溯的,那么每存入一个列的数字,则表示改行回溯过了,该下标就可以表示是该位置的行数。所以我们可以根据这个进行判断。
class Solution {
private:
vector<vector<string> > res;
vector<string> subRes;
vector<int> colRec;
public:
vector<vector<string>> solveNQueens(int n) {
findNQ(n,0);
return res;
}
void findNQ(int n,int rows){
if(rows==n){
res.push_back(subRes);
return;
}
for(int cols=0;cols<n;cols++){
if(isValid(cols,rows)){
string s(n,'.');
s[cols]='Q';
subRes.push_back(s);
colRec.push_back(cols);
findNQ(n,rows+1);
subRes.pop_back();
colRec.pop_back();
}
}
}
bool isValid(int cols,int rows){
// if(rows<colRec.size()) return false;
for(int i=0;i<colRec.size();i++){
if(colRec[i]==cols||abs(i-rows)==abs(colRec[i]-cols)) return false;
}
return true;
}
};
N-Queens II
其实2比1简单一点,因为2只需要返回总共有多少种解,我们不需要记录具体的棋盘摆放方式。所以只需要一个全局变量记录已经放置皇后的列数即可。
不过回溯非常重要!
class Solution {
private:
vector<int> colRec;
int res;
public:
int totalNQueens(int n) {
res=0;
findNQ(n,0);
return res;
}
void findNQ(int n,int rows){
if(rows==n){
res++;
return;
}
for(int cols=0;cols<n;cols++){
if(isValid(rows,cols)){
colRec.push_back(cols);
findNQ(n,rows+1);
colRec.pop_back();
}
}
}
bool isValid(int rows,int cols){
//if(rows<colRec.size()) return false;
for(int i=0;i<colRec.size();i++){
if(colRec[i]==cols||abs(rows-i)==abs(cols-colRec[i])) return false;
}
return true;
}
};