经典算法之八皇后问题

赵昂
• 阅读 3169

八皇后问题是一个古老而又著名的问题,是学习回溯算法的一个经典案例。今天我们就一起来探究一下吧!

经典算法之八皇后问题

时间退回到1848年,国际西洋棋棋手马克斯·贝瑟尔提出了这样的一个问题,

在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问一共有多少种摆法。

后面陆续有不同的学者提出自己的见解。大数学家高斯认为一共有76种摆法,1854年在柏林的象棋杂志上不同的作者发表了共计40种不同的见解,后来还有人利用图论的方法得出共有92种摆法。

而如今,通过我们的计算机以及编程语言我们可以轻松的解决这个问题。

最直接的也是最容易想到的一种解法便是暴力法,我们可以在8×8的格子中任选8个皇后,选定后看是否满足任意两个皇后都不处于同行同列同斜线的条件,若满足则累计满足条件的方案。学习过排列组合的我们发现64取8这个数字达到了40亿,显然是令人难以接受的。

经典算法之八皇后问题
但我们根据这个条件,我们可以人为地做出一些选择,比如根据条件我们可知每行每列最多都只能有一个皇后,这样可以在一定程度上缩减问题的规模。在第一行的某一列选择放置一个皇后,共有8种不同的选择,而第二行只能选择剩下的7列,也就是7种选择,剩下每一行的选择都会递减1,那么总共可供选择的方案有8的阶乘种,已经是一种远优于暴力解法的解法,但是这个阶乘的时间复杂度恐怕也难以令人接受,还有更优的解法吗?

经典算法之八皇后问题

那是自然的,这便是递归回溯的方法。

当我们选择了第一个皇后的位置之后,与其处于同行同列同斜线的位置便都无法被选择,第二个皇后只能放在未被第一个皇后所辐射到的位置上,接着放置第三个皇后,同样不能放在被前两个皇后辐射到的位置上,若此时已经没有未被辐射的位置能够被选择,也就意味着这种摆法是不可行的,我们需要回退到上一步,给第二个皇后重新选择一个未被第一个皇后辐射的位置,再来看是否有第三个皇后可以摆放的位置,如还是没有则再次回退至选择第二个皇后的位置,若第二个皇后也没有更多的选择则回退到第一个皇后,重新进行位置的选择。

经典算法之八皇后问题

整体的方法便如上所述,下面用直观的代码来实现这个算法,

def find_Queen(row):

    if row>7:
        global count
        count+=1
        print_queen()
        return
    
    for column in range(8):
        if check(row,column):
            Queen[row][column]=1
            find_Queen(row+1)
            Queen[row][column]=0

定义一个二维数组Queen,数组中相应位置为1则表示该位置放置皇后,按行来摆放皇后的位置,如果当前选择没法继续往下找到皇后的放置位置,则将之前置为1的重新置为0,也就是回退。而check函数的主要目的是为了筛选皇后的合适位置以满足条件。具体可以分为三块,行列检查,主对角线以及负对角线检查。

def check(row,column):
    
    # 检查行列
    for k in range(8):
        if Queen[k][column]==1:
            return False
        
    # 检查主对角线    
    
    for i,j in zip(range(row-1,-1,-1),range(column-1,-1,-1)):
        if Queen[i][j]==1:
            return False   
        
    # 检查副对角线     
    for i,j in zip(range(row-1,-1,-1),range(column+1,8)):
        if Queen[i][j]==1:
            return False          

    return True

当已经放置了八个皇后时,进入 if 语句,累计数值并且打印出相应的皇后摆放示意图。

经典算法之八皇后问题

实体的星星表示当前位置摆放了皇后,而具体的打印代码如下所示,

def print_queen():
    
    print(Queen)
    for i in range(8):
        for j in range(8):
            if Queen[i][j]==1:
                print('☆ '*j+'★ '+'☆ '*(7-j))
    print("\n\n")

这样,通过递归回溯的办法,我们找到了八皇后的92种解,并且以形式化的方法打印了出来。通过对八皇后问题的学习,我们可以深刻体会到回溯的思想~

点赞
收藏
评论区
推荐文章
Kubrnete Kubrnete
4年前
递归之N皇后问题
问题描述:N皇后问题是指在N\N的棋盘上要摆N个皇后,要求:任何两个皇后不同行,不同列也不再同一条斜线上,求给一个整数N,返回N皇后的摆法数。N皇后问题涉及到回溯的思想。我们通常用递归解决,代码实现会比较简单。递归其实可以看作底层帮我们维护了一个自动push、pop的堆栈。网上也有很多N皇后的相关题解,这篇文章经过我的整理,保
梦
4年前
微信小程序new Date()转换时间异常问题
微信小程序苹果手机页面上显示时间异常,安卓机正常问题image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b691e1230e2f15efbd81fe11ef734d4f.png)错误代码vardate'2021030617:00:00'vardateT
Bill78 Bill78
4年前
Python新式类与经典类(旧式类)的区别
Python新式类与经典类(旧式类)的区别Python中类分两种:旧式类和新式类:➤新式类都从object继承,经典类不需要。➤新式类的MRO(methodresolutionorder基类搜索顺序)算法采用C3算法广度优先搜索,而旧式类的MRO算法是采用
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Stella981 Stella981
3年前
CocosCreator发展趋势与感悟
先分享一个故事:《爱丽丝镜中世界奇遇记》里讲到,爱丽丝遇见了红桃皇后,红桃皇后牵着她的手往前跑,但是不管她们跑得多快,一直跑到精疲力尽,最后还是停留在原地。爱丽丝说:“要是在我们国家,像这样奔跑,一定会跑到一个新的地方。”红桃皇后不屑地说:“那你们是慢吞吞的国家,在我们这个世界,你要想待在原地,就得使出全身力量拼命跑”。转眼之间就要到
迁移学习核心技术的开发与应用
一、机器学习简介与经典机器学习算法介绍1.什么是机器学习?2.机器学习框架与基本组成3.机器学习的训练步骤4.机器学习问题的分类5.经典机器学习算法介绍章节目标:机器学习是人工智能的重要技术之一,详细了解机器学习的原理、机制和方法,为学习深度学习与迁移学习打下坚实的基础。二、深度学习简介与经典网络结构介绍1.神经网络简介2.神经网络组件简介3.神经网
人工智能人才培养
No.1第一天一、机器学习简介与经典机器学习算法介绍什么是机器学习?机器学习框架与基本组成机器学习的训练步骤机器学习问题的分类经典机器学习算法介绍章节目标:机器学习是人工智能的重要技术之一,详细了解机器学习的原理、机制和方法,为学习深度学习与迁移学习打下坚实的基础。二、深度学习简介与经典网络结构介绍神经网络简介神经网络组件简介神经网络训练方法卷积神经网络介
贾蔷 贾蔷
1星期前
牛客网NC67汉诺塔问题:递归算法解析(附完整C++代码)
一、问题背景汉诺塔(TowerofHanoi)是经典的问题,源于一个古老的传说。游戏规则:1.一次只能移动一个圆盘1.大圆盘不能放在小圆盘上面1.所有圆盘从起始柱移动到目标柱二、原理采用将问题分解:1.将n1个盘子从起始柱移到辅助柱(子问题)1.将第n个盘
贾蔷 贾蔷
56分钟前
【动态规划入门】力扣509题:斐波那契数列的经典解法与优化思路
一、题目解读‌是一个经典的数学问题,在计算机科学中常被用作教学的入门案例。这个神奇的数列从0和1开始,后续每个数字都是前两个数字之和。题目要求我们计算第n个,看似简单的问题背后却蕴含着重要的算法思想。当n较小时,这个问题似乎微不足道,但随着n的增大,不同的