[算法入土之路]n皇后问题(位运算加速)

n皇后问题的算法规模为 O(n^n) 无法改变, 但是我们可以在常数上做优化(通过位运算)

def NQueens(n):
    '''
    利用位运算提高运算速率
    :param n: 几个皇后
    :return:
    '''
    n = (1 << n) - 1  # 生成二进制为 n 个 1 的数字

    def inner(n_, col, left, right):
        '''
        :param n_: 总行: 例: 八皇后 n_ = 0」11111111
        :param col: 列限制
        :param left: 左斜线限制
        :param right: 右斜线限制
        :return: 当前获得解的个数
        '''
        if col == n_:  # 当绘制完最后一行 得到一个解
            return 1
        pos = n_ & (~(col | left | right))
        '''
            n」 表示前面无限为都是n
            col | left | right -> 0」 0 代表可以放皇后的位置, 1 代表不可以放皇后的位置
            ~ -> 1」 1 代表可以放皇后的位置 0 代表不可以放皇后的位置
            n_ & -> 0」1 代表可以放皇后的位置 0 代表不可以放皇后的位置
        '''
        res = 0  # 解的个数
        while pos:  # 如果还有皇后可以放置的位置
            cur_loc = pos & (~pos + 1)  # 获得最右面的一个1 即从右往左找皇后可以放置的位置
            pos -= cur_loc  # 使当前可以放置皇后的位置变为不可以放置皇后的位置
            res += inner(n_, col | cur_loc, (left | cur_loc) << 1, (right | cur_loc) >> 1)
            '''
            例子: 八皇后最外层第一次循环              八皇后第二层 第一次循环
            pri_seq    1 1 1 1 1 1 1 1          pri_seq    1 1 1 1 1 1 1 1     # 原始序列        
            pos        1 1 1 1 1 1 1 1          pos        1 1 1 1 1 1 0 0     # 当前可以放置皇后的位置
            left       0 0 0 0 0 0 0 0          left       0 0 0 0 0 0 1 0     # 左限制
            right      0 0 0 0 0 0 0 0          right      0 0 0 0 0 0 0 0     # 右限制
            cur_loc    0 0 0 0 0 0 0 1          cur_loc    0 0 0 0 0 1 0 0     # 当前获得的可以放置皇后的位置
            left|cur   0 0 0 0 0 0 0 1          left|cur   0 0 0 0 0 1 1 0     # 左限制与当前皇后位置作 或操作
            ↑ << 1     0 0 0 0 0 0 1 0          ↑ << 1     0 0 0 0 1 1 0 0     # 向左移一位 代表下一行的左限制
            right|cur  0 0 0 0 0 0 0 1          right|cur  0 0 0 0 0 0 1 0     # 右限制与当前皇后位置作 或操作 
            ↑ >> 1     0 0 0 0 0 0 0 0          ↑ >> 1     0 0 0 0 0 0 0 1     # 向右移一位 代表下一行的右限制
              
            '''
        return res

    return inner(n, 0, 0, 0)

print(NQueens(4))

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值