题目描述:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入:4
输出:[
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],
["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
方法1:
主要思路:
(1)使用回溯方法;
(2)其实主要的难点是如何表示斜线上的皇后的存在性;
(3)从左上到右下的斜线,使用横坐标减去纵坐标是定值,从右上到左下的斜线,使用横坐标加上纵坐标是定值;
class Solution {
public:
//根据各行中皇后所在的位置生成对应的字符串
void get_board(vector<int>& queens,int n,vector<string>& tmp){
for(int i=0;i<n;++i){
string row_str(n,'.');
row_str[queens[i]]='Q';
tmp.push_back(row_str);
}
}
void backtrack(vector<int>&queens,unordered_set<int>& col,unordered_set<int>& dia1,unordered_set<int>& dia2,int& n,int row,vector<vector<string>>& res){
if(row==n){//说明找到了所有的皇后的位置
//根据当前各行中的皇后的位置,生成对应的结果字符串
vector<string> tmp;
get_board(queens,n,tmp);
res.push_back(tmp);
return;
}
else{
//找当前行中,皇后的可能的存储位置
for(int i=0;i<n;++i){
if(col.count(i)){//是否存在列冲突
continue;
}
int index1=row-i;
if(dia1.count(index1)){//是否存在从左上角到右下角的斜线上的冲突
continue;
}
int index2=row+i;
if(dia2.count(index2)){//是否存在从右上角到左下角的斜线上的冲突
continue;
}
//将当前行的当前位置上放入皇后,并更新相关的标识数据
queens[row]=i;
col.insert(i);
dia1.insert(index1);
dia2.insert(index2);
//回溯
backtrack(queens,col,dia1,dia2,n,row+1,res);
//复原数据
queens[row]=-1;
col.erase(i);
dia1.erase(index1);
dia2.erase(index2);
}
}
}
vector<vector<string>> solveNQueens(int n) {
unordered_set<int> col;//标识列
unordered_set<int> dia1;//标识从左上角到右下角的斜线
unordered_set<int> dia2;//标识从右上角到左下角的斜线
vector<vector<string>> res;//存储结果
vector<int> queens(n,-1);//存储回溯过程中,皇后在各行中的位置
backtrack(queens,col,dia1,dia2,n,0,res);//回溯
return res;
}
};