DFS算法3行代码解决8皇后(N皇后)问题

本篇文章源自“讲算法的熊船长”B站直播节目和公众号文章。(如转载,请将此声明和内容一并转载)


8皇后问题

       在国际象棋中,棋盘有8行8列共64个格子,皇后可以走直线和斜线(米字形),8皇后问题是在棋盘上放8个皇后,要求所有皇后都不会互相攻击。

N皇后问题

        N皇后问题是8皇后问题的扩展版,即给一个N*N的棋盘,要求放置N个皇后。

DFS

        N皇后问题是一个很适合用计算机求解的问题,学习过编程的朋友应该都遇到过。求解N皇后问题可以用一个很经典的算法,深度优先搜索算法(Depth First Search),或者叫做回溯算法(backtracking),很多朋友搞不清这两个算法是什么关系,其实这两个算法是同一回事。

       我们在直播中用了超过10种方法来求解这道题(Leetcode 51),下面是其中的一个版本,这个版本只有7行代码。计算机科学家高纳德曾说,计算机程序=数据结构+算法,选择适当的数据结构会让算法变得简洁。面对不同的具体问题,如何选择数据结构和算法,这需要思考和很多练习。

# Leetcode 51
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        def sch(qlst: List[int], x: int, y: int, z: int, qs: List[int]) -> List[List[str]]:
            if len(qlst) == n:
                return [[''.join(['Q' if (1<<i) & q else '.' for i in range(n)]) for q in qlst]]  
            return sum([sch(qlst+[q], x|q, (y|q)>>1, (z|q)<<1, qs) for q in qs if q & (x|y|z) == 0], [])
        return sch([], 0, 0, 0, [1<<i for i in range(n)])

        Leetcdoe 52题也是N皇后问题,与51不同之处是该题只需输出解的个数,我们可以用5行代码解决这个问题,这5行代码中有2行是Leetcode的接口,求解这个问题只需3行代码。

# Leetcode 52
class Solution:
    def totalNQueens(self, n: int) -> int:
        def s(l: List[int], x: int, y: int, z: int, qs: List[int]) -> List[List[str]]:
            return 1 if len(l)==n else sum([s(l+[q], x|q, (y|q)>>1, (z|q)<<1, qs) for q in qs if q&(x|y|z)==0])
        return s([], 0, 0, 0, [1<<i for i in range(n)])

对称性优化

        N皇后问题的解中存在这很多对称性,其中一个最容易观察到的是左右的镜像对称,通过使用这个对称的特性可以进一步优化算法,将搜索空间缩小接近一半(对于偶数的N是刚好一半)。

        怎样在我们已有的程序中使用对称性优化呢?这似乎并不显然,其实这个优化非常容易加进去。我们只要在第一行(或列)只搜索一半即可。

# Leetcode 52
class Solution:
    def totalNQueens(self, n: int) -> int:
        def s(l:int, x: int, y: int, z: int, qs: List[int]) -> List[List[str]]:
            return 1 if l==n else sum([s(l+1, x|q, (y|q)>>1, (z|q)<<1, qs) for q in qs if q&(x|y|z)==0])
        t = 2 * sum([s(1, 1<<i, (1<<i)>>1, (1<<i)<<1, [1<<j for j in range(n)]) for i in range(n//2)])
        return t + (s(1, 1<<(n//2), (1<<(n//2))>>1, (1<<(n//2))<<1, [1<<j for j in range(n)]) if n&1 else 0)

欢迎各位朋友有空常来B站直播间一起交流学习!如果您喜欢我创造的内容,请关注、点赞、转发支持一下,助力纸质版《算法之法》早日面市!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值