N皇后问题-位运算解法
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案数。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
https://leetcode.cn/problems/n-queens/description/
// 用位信息表示路径实现的N皇后问题,推荐
public static int totalNQueens2(int n) {
if (n < 1) {
return 0;
}
// n = 5
// 1 << 5 = 0...100000 - 1
// limit = 0...011111;
// n = 7
// limit = 0...01111111;
int limit = (1 << n) - 1;
return f2(limit, 0, 0, 0);
}
// limit : 当前是几皇后问题
// 之前皇后的列影响:col
// 之前皇后的右上 -> 左下对角线影响:left
// 之前皇后的左上 -> 右下对角线影响:right
public static int f2(int limit, int col, int left, int right) {
if (col == limit) {
// 所有皇后放完了!
return 1;
}
// 总限制
int ban = col | left | right;
// ~ban : 1可放皇后,0不能放
int candidate = limit & (~ban);
// 放置皇后的尝试!
int place = 0;
// 一共有多少有效的方法
int ans = 0;
while (candidate != 0) {
// 提取出最右侧的1
// 0 0 1 1 1 0
// 5 4 3 2 1 0
// place :
// 0 0 0 0 1 0
// candidate :
// 0 0 1 1 0 0
// 5 4 3 2 1 0
// place :
// 0 0 0 1 0 0
// candidate :
// 0 0 1 0 0 0
// 5 4 3 2 1 0
// place :
// 0 0 1 0 0 0
// candidate :
// 0 0 0 0 0 0
// 5 4 3 2 1 0
place = candidate & (-candidate);
candidate ^= place;
ans += f2(limit, col | place, (left | place) >> 1, (right | place) << 1);
}
return ans;
}
如果要返回具体方案:
class Solution {
public:
void f(int limit, int col, int left, int right, vector<int>& p,
vector<vector<string>>& res) {
if (limit == col) {
vector<string> a;
int n = p.size();
for (int i = 0; i < n; i++) {
string s(n, '.');
s[p[i]] = 'Q';
a.push_back(s);
}
res.push_back(a);
return;
}
int ban = col | left | right;
int ke = limit & (~ban);
while (ke > 0) {
int c = ke & (-ke);
ke ^= c;
int now = 0;
int temp = c;
while (temp >>= 1) {
now++;
}
p.push_back(now);
f(limit, col | c, ((left | c) >> 1), ((right | c) << 1), p, res);
p.pop_back();
}
}
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> res;
vector<int> p;
int limit = (1 << n) - 1;
f(limit, 0, 0, 0, p, res);
return res;
}
};
这个做法非常快,可以在200毫秒内解决14皇后问题。
可以在10秒内解决16皇后问题

浙公网安备 33010602011771号