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皇后问题

posted @ 2026-03-04 17:27  Lambda_L  阅读(1)  评论(0)    收藏  举报