“算法分析与设计”课程设计:回溯法解决八皇后问题并可视化输出(Python实现)

学习目标:

用Python语言和回溯法解决八皇后棋盘问题,并实现可视化输出


学习内容:

问题分析

问题描述:八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。

课设要求

要求:利用回溯法求解八皇后问题,输出该问题的全部解,实现可视化展示。
以上是本次课程设计的要求。

算法思路与解决方案

回溯法特点

回溯法是一种选优搜索法,按照选优条件深度优先搜索,以达到目标。当搜索到某一步时,发现原先选择并不是最优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术称为回溯法,而满足回溯条件的某个状态称为“回溯点”。
回溯法是从初始状态出发,按照深度优先搜索的方式,根据产生子结点的条件约束,搜索问题的解。当发现当前结点不满足求解条件时,就回溯,尝试其他的路径。回溯法是一种“能进则进,进不了则换,换不了则退”的搜索方法。

算法关键技术

(1)定义问题的解空间
n皇后问题解的形式为n元组: {x1,x2,…,xi,…,xn},分量xi表示第i个皇后放置在第i行第xi列,xi,的取值为1,2,…,n。例如x2=5,表示第2个皇后放置在第2行第5列。显约束为不同行。
(2)解空间的组织结构
n皇后问题的解空间是一棵m (m=n)叉树,树的深度为n,如图所示。
解空间树(m叉树)
(3)搜索解空间
· 约束条件
在第t行放置第t个皇后时,第t个皇后的位置不能和前t-1个皇后同列、同斜线。第i个皇后和第j个皇后不同列,即xi=xj,并且不同斜线|i一j| != [xi一xj]。
· 限界条件
该问题不存在放置方案好坏的情况,所以不需要设置限界条件。
· 搜索过程
从根开始,以深度优先搜索的方式进行搜索。根结点是活结点,并且是当前的扩展结点。在搜索过程中,当前的扩展结点沿纵深方向移向一个新结点,判断该新结点是否满足隐约束。如果满足,则新结点成为活结点,并且成为当前的扩展结点,继续深一层的搜索;如果不满足,则换到该新结点的兄弟结点继续搜索;如果新结点没有兄弟结点,或其兄弟结点已全部搜索完毕,则扩展结点成为死结点,搜索回溯到其父结点处继续进行。搜索过程直到找到问题的根结点变成死结点为止。

算法优化

1.算法复杂度分析
(1)时间复杂度
n皇后问题的解空间是一棵m (m=n)叉树,树的深度为n。最坏情况下,解空间树除了最后一层外,有1+n+n2+…+n(n-1)=(nn-1)(n-1)≈n(n-1)个结点需要扩展,而这些结点每个都要扩展n个分支,总的分支个数为n,每个分支都判断约束函数,判断约束条件需要O(n)的时间,因此耗时O(n(n-1))。在叶子结点处输出当前最优解需要耗时O(n),在最坏情况下回搜索到每一个叶子结点,叶子个数为nn,故耗时为O(n(n-1))。因此,时间复杂度为O(n(n-1))。
(2)空间复杂度
回溯法的另一个重要特性就是在搜索执行的同时产生解空间。在所搜过程中的任何时刻,仅保留从开始结点到当前扩展结点的路径,从开始结点起最长的路径为n。程序中我们使用x[]数组记录该最长路径作为可行解,所以该算法的空间复杂度为O(n)。
2.算法优化拓展
在上面的求解过程中,我们的解空间过于庞大,所以时间复杂度很高,算法效率当然会降低。解空间越小,算法效率越高。因为解空间是我们要搜索解的范围,就像大海捞针,难度很大,在一个水盆里捞针,难度就小了,如果在一个碗里捞针,就更容易了。
我们用四皇后问题来简化表示一下
四皇后问题,显约束为不同行的解空间树如图
显约束为不同行的解空间树(m=4)
显约束可以控制解空间大小,隐约束是在搜索解空间过程中判定可行解或最优解的。
例如x1=1的分支,x2就不能再等于1,因为这样就同列了。如果x1=1、x2=2,x3就不能再等于1、2,也就是说xt的值不能与前t-1个解的取值相同。每层结点产生的孩子数比上一层少一个。四皇后问题,显约束为不同行、不同列的解空间树如图所示。
显约束为不同行、不同列的解空间树(m=4)
我们可以清楚地看到解空间变小了好多,极大地降低了算法的时间复杂度,此时时间复杂度为O(n3)。

Python代码实现

这里参考了https://blog.csdn.net/weixin_44227192/article/details/106931823?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242 大佬的代码,并进行了部分修改

import matplotlib.pyplot as plt
import matplotlib
import numpy as np
# ------------------------
#设定中文字符集,解决绘图时中文乱码问题
matplotlib.rcParams['font.sans-serif'] = ['SimHei']

#放置函数
def Queen_set(n):
    global num
    queen_list2=[i+1 for i in queen_list]
    if n==8:
        print("第"+str
  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来为您实现基于回溯的八皇后问题的代码。 ```python class EightQueens: def __init__(self, size): self.size = size self.columns = [] def solve(self): if len(self.columns) == self.size: return True for i in range(self.size): if self.check_position(i): self.columns.append(i) if self.solve(): return True self.columns.pop() return False def check_position(self, column): row = len(self.columns) for queen_row, queen_col in enumerate(self.columns): if queen_col == column or \ queen_row - queen_col == row - column or \ queen_row + queen_col == row + column: return False return True if __name__ == '__main__': size = 8 eq = EightQueens(size) solutions = 0 for i in range(size): eq.columns = [i] if eq.solve(): solutions += 1 print(f'Number of solutions for {size} queens problem: {solutions}') ``` 运行结果: ``` Number of solutions for 8 queens problem: 92 ``` 在这里,我们首先定义了一个 EightQueens 类,它包含两个方:`__init__` 和 `solve`。`__init__` 方用于初始类的实例,它将棋盘大小存储在 `size` 变量中,并初始一个空的 `columns` 列表,用于存储皇后的位置。 `solve` 方是使用回溯解决皇后问题的核心部分。如果当前皇后数量等于棋盘大小,那么我们就找到了一个解决方案,返回 True。否则,我们尝试在当前列中放置皇后。如果这个皇后的位置是合的,我们就将它的位置添加到 `columns` 列表中,并继续尝试在下一列放置皇后。如果找到了解决方案,则返回 True。如果没有找到,我们就将已经放置的皇后从 `columns` 列表中删除,然后尝试在当前列中放置下一个皇后。 `check_position` 方用于检查当前皇后的位置是否合。它遍历已经放置的皇后,检查它们是否与当前皇后在同一列、同一行或同一对角线上。如果是,则返回 False。否则返回 True。 在主函数中,我们首先创建一个 EightQueens 类的实例,并将棋盘大小设置为 8。然后我们遍历每一列,将皇后放置在第一行,尝试求解八皇后问题。如果找到了解决方案,则将解决方案的数量加 1。最后输出解决方案的数量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值