n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,
并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
思路:
失败或成功后返回上一步的状态。
int test[n][n];
stack<pair<int, int>> queen;
int sum; //可能的结果数
bool fun(row,col) 尝试在第row行, 第col列放
{
//看是否违反规定
入queue;
bool tag = fun1(queen); //看queen中黄后位置是否符合规定
if(tag == false)
{
出quque; //回溯
return false;
}
else
{
if(row == n-1)
{
打印结果;
出栈一次; //回溯
sum++;
return true;
}
for(int i=0;i<n;i++)
{
fun(row + 1, i);
}
}
}
for(int i=0; i<n; i++)
{
fun(0, i);
}
关于如何判断queen是否违反条件:
用新加入的点的 之前老的点一个一个比较
(i,j)(m, n)
i!=m
j!=n
i-j != m-n 左上到右下
i+j != m+n 左下到右上
class Solution {
public:
bool valid(int n, vector<int>& cols) {
if (cols.size() <= 1)
return true;
int row = cols.size() - 1;
int col = cols.back();
for (int r = 0; r < row; ++r) {
int c = cols[r];
if (c == col || abs(c - col) == abs(r - row))
return false;
}
return true;
}
void backtrace(int n, vector<int>& cols, vector<vector<int> >& res) {
if (!valid(n, cols)) return;
if (cols.size() == n) {
res.push_back(cols);
return;
}
for (int i = 0; i < n; ++i) {
cols.push_back(i);
backtrace(n, cols, res);
cols.pop_back();
}
}
vector<vector<string>> solveNQueens(int n) {
vector<int> cols;
vector<vector<int> > all;
backtrace(n, cols, all);
vector<vector<string> > res;
for (auto& v : all) {
vector<string> s;
for (auto& c : v) {
string t(n, '.');
t[c] = 'Q';
s.push_back(t);
}
res.push_back(s);
}
return res;
}
};
dfs+位运算剪枝
只要结果总数n时。
使用常规深度优先一层层搜索
使用三个整形分别标记每一层哪些格子可以放置皇后,
这三个整形分别代表列、左斜下、右斜下(_col, ld, rd_),
二进制位为 11 代表不能放置,00 代表可以放置
核心两个位运算:
x & -x 代表除最后一位 11 保留,其它位全部为 00
x & (x - 1) 代表将最后一位 11 变成 00
class Solution {
public:
int totalNQueens(int n) {
dfs(n, 0, 0, 0, 0);
return this->res;
}
void dfs(int n, int row, int col, int ld, int rd) {
if (row >= n) { res++; return; }
// 将所有能放置 Q 的位置由 0 变成 1,以便进行后续的位遍历
int bits = ~(col | ld | rd) & ((1 << n) - 1);
while (bits > 0) {
int pick = bits & -bits; // 注: x & -x
dfs(n, row + 1, col | pick, (ld | pick) << 1, (rd | pick) >> 1);
bits &= bits - 1; // 注: x & (x - 1)
}
}
private:
int res = 0;
};