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

本文介绍了一种使用Python和回溯法解决八皇后问题的课程设计,详细解析了问题分析、算法思路、关键技术、优化方法以及Python代码实现。通过代码实现了问题的可视化输出,并分享了在解决过程中遇到的字体问题和结果格式调整的解决方案。
摘要由CSDN通过智能技术生成

学习目标:

用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(num)
解决八皇后问题。从第一行开始,放第一个皇后,放好皇后以后,她所在的行,列和对角线上的每一个位置就是她的管辖范围,别的皇后没有权利干涉,否则死无藏身之地。 然后,第二个皇后,从第二行的第一列开始判断所在的位置是否是别的皇后的管辖范围,找到第一个还没有被占据的位置,则将其占为己有。暂,该皇后停在该位置。然后,第三个到第八个皇后依次从第三行,第四行,… ,到第八行的第一列开始寻求自己的位置。假如到第i个皇后,已经没有任何位置可选,则第i-1个皇后必须往后移动进行协调,同样,假如第i-1个皇后往后移动没有找到空位置,则第i-2个皇后必须往后移动,进行协调,当找到空位置,暂停下,将下一个皇后重新从第一列开始寻找空位置。重复上述过程,直到所有皇后都停下来。则得到了第一个。要想产生所有的,则当产生第一个以后,第八个皇后往后移动,找下一个可以利用的空位置,找不到,则第七个皇后必须往后移动,若找到空位置则停下,第八个皇后从第八行第一列重新试探,找到空位置。一直这样,直到第一个皇后将第一行遍历完。得到的就是所有。 三、 概要设计: ***************类型及相关变量定义***************** //位置信息类型 typedef struct { int row; int col; }PosType; //皇后类型 typedef struct Queen{ PosType pos; int number; //第几号皇后 }QueenType; //栈节点类型 typedef struct Note{ QueenType queen; struct Note *next; }NoteType; //棋盘,某一位置chessboard[i][j]上有皇后,则该位的值变为皇后序号。同样,该皇后的势 //力范围内的位置上的值全部变为该皇后的序号。 int chessboard[8][8]; //结果集,共92种,每一种中记录8个位置信息。 PosType ResultSet[92][8]; //定义一个栈,保存信息 Typedef struct{ NoteType head; Int size; }QueenStack; //定义一个栈,存放皇后信息 QueenStack qstack; *************相关操作**************** //初始化棋盘,开始每个位置上都没有皇后,值全为0;并给8个皇后编号。 void initChessboard(); //回溯求八皇后问题的所有,皇后协调算法 void queenCoordinate(); //输出所有 void printResult();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值