题目:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
思路:
从开始学数据结构就看过这个大名鼎鼎的问题,终于可以磕磕绊绊的自己写出来了最简单的版本了;)
回溯法。
x在每一行去尝试,然后在这一行去试每一列y。找到与之前皇后不冲突的(x,y),放上新皇后。然后试下一行x+1。
每一行都成功放上皇后,出递归,并记录这个答案。
某一行找不到皇后,回溯。
因为要找所有答案,会回溯尝试所有可能。
清华的c++数据结构课本了有很好的解答。
在答案中用了一个结构体表示点坐标,重载了==,用来判断是否相互攻击。
class Solution {
public:
int size;
struct Point { //结构体 点坐标(x,y)
int x, y;
Point(int x0, int y0) :x(x0), y(y0) {};
bool operator==(Point &p) {
return (x + y) == (p.x + p.y) || (x - y) == (p.x - p.y) || (x == p.x) || (y == p.y);
}; //重载==,行列斜线冲突
};
void dfs(vector<Point> &tmpres, vector<vector<Point>> &res) { //递归
if ( tmpres.size()==size) {
res.push_back(tmpres); return; //一个解
}
int nextx = tmpres.size(); //下一个x
for (int i = 0; i < size; i++) {
bool ok = true;
Point nextp(nextx, i); //尝试y
for (auto item : tmpres) {
if (nextp == item) ok = false; //与之前点冲突
}
if (!ok) {
continue; //冲突continue
}
tmpres.push_back(nextp); //不冲突,加入该点
dfs(tmpres, res); //继续递归
tmpres.pop_back(); //回溯时记得复原之前的修改
}
}
vector<vector<string>> solveNQueens(int n) {
size = n;
vector<vector<Point>> res;
vector<Point> tmpres;
dfs(tmpres, res); //递归
vector<vector<string>> stringres; //string答案
for (auto tmpres : res) {
vector<string> stringtmpres(size, string(size, '.')); //先初始化n*n的'.'
for (auto p : tmpres) {
stringtmpres[p.x][p.y] = 'Q'; //把皇后改成Q
}
stringres.push_back(stringtmpres); //加入答案
}
return stringres;
}
};