51. N皇后
难度困难
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],
["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。
当然,她横、竖、斜都可走一到七步,可进可退。(引用自 百度百科 - 皇后 )
来源: 添加链接描述
代码思路:
这道题是经典的回溯题,开始我们先要考虑一下怎么生成棋盘并且将“皇后”放入其中,我们可以用二维数组来建立起一个棋盘mark,之后将数组中的每个元素设置成为0来代表是空位,之后用1来代表放置的皇后和皇后所能吃子的范围(就是不能再放入新皇后的位置)之后我们用方向数组的方法来将棋盘上不能放皇后的位置改成1,这样棋盘的函数就写好了。
接下来我们再建立一个和棋盘mark类似的数组location来保存皇后的位置,建立方式和棋盘一样,只不过是用字符串的形式,在没有皇后的位置用‘.'来表示,用’Q‘来表示皇后的位置。
最后开始建立递归函数,因为每一行最多只能有一个皇后,那么我们就每次递归一行棋盘来考虑,每一行只要mark位置上是0就可以放皇后,之后每次递归到下一行,在递归之前用一个临时棋盘来保存现在的棋盘用来之后的回溯用,当我们递归到某行的时候发现没有皇后的位置可以放置了,那么我就要回溯了,返回到没有放皇后的时候,之后换成另一个位置来放置皇后的位置,经过这样的递归一直到n行都放置了皇后就可以结束递归了。
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
class Solution {
public:
vector<vector<string> >solveNQueens(int n)
{
vector<vector<string> >result;
vector<vector<int> >mark;
vector<string>location;
for (int i = 0;i < n;++i)
{
mark.push_back((vector<int>()));
for (int j = 0;j < n;++j)
{
mark[i].push_back(0);
}
location.push_back("");
location[i].append(n, '.');
}
generate(0, n, location, result, mark);
return result;
}
private:
void put_down_the_queen(int x, int y,//棋盘函数
vector<vector<int> >& mark)
{
static const int dx[] = { -1,1,0,0,-1,-1,1,1 };
static const int dy[] = { 0,0,-1,1,-1,1,-1,1 };
mark[x][y] = 1;
for (int i = 1;i < mark.size();++i)
{
for (int j = 0;j < 8;++j)
{
int new_x = x + i * dx[j];
int new_y = y + i * dy[j];
if (new_x >= 0 && new_x < mark.size()
&& new_y >= 0 && new_y < mark.size())
mark[new_x][new_y] = 1;
}
}
}
void generate(int k, int n, vector<string>& location,//递归函数
vector<vector<string> >& result, vector<vector<int> >& mark)
{
if (k == n)
{
result.push_back(location);
return;
}
for (int i = 0;i < n;++i)
{
if (mark[k][i] == 0)
{
vector<vector<int> >tmp_mark = mark;
location[k][i] = 'Q';
put_down_the_queen(k, i, mark);
generate(k + 1, n, location, result, mark);
mark = tmp_mark;
location[k][i] = '.';
}
}
}
};
int main()
{
//测试案例
vector<vector<string> >result;
Solution solve;
result = solve.solveNQueens(4);
for (int i = 0;i < result.size();++i)
{
cout << "i = " << i<<endl;
for (int j = 0;j < result[i].size();j++)
{
cout << result[i][j].c_str()<<endl;
}
cout << endl;
}
}