n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
写在前面:
LeetCode有两道题,N皇后和N皇后II,N皇后是把解法一一罗列,而N皇后II是求出N皇后的的解法数目,我这里先从N皇后II求解,再来写N皇后的解答。
其实N皇后问题的解法就是穷举所有情况,只不过是聪明的穷举(即回溯,有些情况下面怎么都无法满足N皇后的规则,就放弃下面的所有解),结合深度优先搜索即可求出所有解。
n皇后问题规则,皇后们不能在同行,同列, 同斜线。
N皇后II:求解的数量
代码:
class Solution {
private:
vector<int> arr;//用来存储皇后的位置,arr[k]=i代表第k行第i列有一个皇后。
int count;//用来统计有多少种解法
int size;//存储N皇后的大小,也就是矩阵的大小,8皇后这个变量值就为8
public:
bool check(int row, int col)//判断row行col列是否能够放皇后,判断行列斜线是否满足要求
{
for (int i = 0; i < row; ++i)//是否跟之前的row行冲突
{
//由arr的数组定义可知,每一行放一个皇后,就解决了不在同行的问题
//下面if判断语句主要判断列和斜线是否满足要求
//比较斜线, 因为不再同一斜率为1或者-1的斜线。(row - i) / (col - arr[i]) != 1 或 -1,
//可以取巧用绝对值函数: abs(row - i) != abs(col - arr[i])
if (col == arr[i] || abs(row - i) == abs(col - arr[i]))
{
return false;//不满足条件,直接return false
}
}
return true;
}
void solve(int k) {//k为当前打算在第k行放置皇后
if (k == size)//当k与size相等的时候说明在最后一行已经放好皇后了
{
count++;//解法数量加一
return;
}
for (int i = 0; i < size; ++i)//判断第0列到第size-1列是否能放皇后
{
if (check(k, i))//检查第k行第i列是否能放置皇后
{
arr[k] = i;//如果上面条件判断为true,说明可以在第k行第i列放置皇后,记录数组中
solve(k + 1);//递归,判断下一行哪些列能放置皇后
}
}
}
int totalNQueens(int n) {
size = n;//初始化size,n皇后就有n行n列
count = 0;//初始计数为0
arr = vector<int>(n);//初始化数组长度
solve(0);//从第0行开始判断
return count;//返回解法数量
}
};
N皇后:求具体的解
写在前面:
基于上面N皇后II的代码,站在巨人的肩膀上,加以小小的改造,即可求N皇后
代码:
class Solution {
private:
vector<vector<string>> res;//储存具体的解
vector<int> arr;
int count;
int size;
public:
bool check(int row, int col)
{
for (int i = 0; i < row; ++i)
{
if (col == arr[i] || abs(row - i) == abs(col - arr[i]))
{
return false;
}
}
return true;
}
void solve(int k, vector<string> &v) {//此处使用&v而不直接用v,能节省非常多的内存和时间
if (k == size)
{
res.push_back(v);//把正确的结果集放入res数组中
count++;
return;
}
for (int i = 0; i < size; ++i)
{
string s(size, '.');//比如8皇后就是初始化8个点即“........”
if (check(k, i))
{
arr[k] = i;
s[i] = 'Q';//将能够放皇后的位置改成‘Q’,比如在第一列放皇后,即“Q.......”
v.push_back(s);//push当前行的结果入数组
solve(k + 1, v);
v.pop_back();//用完之后马上弹出,不影响下一列的判断
}
}
}
vector<vector<string>> solveNQueens(int n) {
size = n;
count = 0;
arr = vector<int>(n);
vector<string> v;//最后靠这个v存入每一次满足条件的结果集
solve(0, v);
return res;
}
};