问题描述
思路
最暴力的解法就是在棋盘上把所有的位置都遍历一遍,并判断当前位置能否放皇后……那么此题就可以递归回溯算法,用递归,首先就要确定递归的参数,
void getQueens(int n,int index,vector & row)
n代表皇后的个数,index表示当前考虑将皇后放到第index行,
row[i]=k,表示第i行的第k列放了皇后。
其次,此题的关键就是判断当前位置能不能放皇后,这里有一定的技巧性,我定义了以下向量来存储
vector col,dia1,dia2;
**col[i]**表示第i列是否已经访问过;
dia1表示左下到右上对角线是否被访问过
其中左下到右上对角线上的点有一个特点,就是横坐标加纵坐标等于一个常数,并且第一条对角线上的横纵坐标相加为0,于是我们用 dia1[index+i]来表示该点的第一类对角线是否被访问过
dia2表示右上到左下对角线是否被访问过
其中的特点就是,该对角线上的横坐标减纵坐标为一个常数,但是常数的最小值为n-1,所以为了使用方便,我们就用dia2[index-i+n-1]来表示该点的第二类对角线是否被访问过;
** 其中对于dia1,dia2都有2*n-1条对角线**
代码
class Solution {
vector <vector <string> > res;
vector <bool> col,dia1,dia2;
vector <string> transform(int n,vector <int> &row)
{//这里就是根据row来画出对应的解
vector <string> temp(n,string(n,'.'));
for(int i=0;i<n;i++) {
temp[i][row[i]]='Q';
}
return temp;
}
void getQueens(int n,int index,vector <int>& row) {
if(index==n) {
res.push_back(transform(n,row));
return;
}
for(int i=0;i<n;i++) {
if(!col[i]&&!dia1[index+i]&&!dia2[index-i+n-1]) {
row.push_back(i);
col[i]=true;
dia1[index+i]=true;
dia2[index-i+n-1]=true;
getQueens(n,index+1,row);
row.pop_back();
col[i]=false;
dia1[index+i]=false;
dia2[index-i+n-1]=false;
}
}
}
public:
vector<vector<string>> solveNQueens(int n) {
if(n==0) return res;
vector <int> row;
col=vector <bool> (n,false);
dia1=vector <bool> (2*n-1,false);
dia2=vector <bool> (2*n-1,false);
getQueens(n,0,row);
return res;
}
};