数据结构解决八皇后问题(java版)

摘  要

八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。在 8*8 格的 国际象棋棋盘上,安放八个皇后,要求没有一个皇后能够“吃掉”任何其他一个 皇后,即任意两个皇后都不能处于同一行、同一列或同一条对角线上,求解有多 少种摆法。有人用图论的方法得出结论,有 92 种摆法。

本文研究的课题是,设计算法、编写程序求得八皇后问题可行的方案。本文 采用回溯算法结合递归的思想进行程序的设计:将一个皇后按照规则从首行开始 放置,然后在下一行按规则放置皇后,重复上述步骤,当出现错误解时回退至上 一行或者上多行重新放置。最终达成“放得下八个皇后”及“八个皇后不互相吃” 的条件的都是八皇后问题的解。

关键词八皇后问题  回溯算法 递归 Java GUI界面

章  绪  论

1.1 课设主要研究问题

八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十 九世纪著名的数学家高斯 1850 年提出:在 8*8 格的国际象棋棋盘上,安放 8 个 皇后,要求没有一个皇后能够“吃掉”任何其他一个皇后,即任意两个皇后都不 能处于同一行、同一列或同一条对角线上,求解有多少种摆法。高斯认为有 76 种方案。1854 年在柏林的象棋杂志上不同的作者发表了 40 种不同的解,后来有人用图论的方法得出结论,有 92 种摆法。

1.2 课设应用的理论知识

1.2.1  理论知识

本次课程设计中应用的理论知识有:回溯算法、递归思想、Java语言循环语句 for 语句的灵活运用、Java语言条件语句 if——else 的运用、数据结构中树知识的灵活运用以及栈、数组的掌握。 回溯算法:解决一个回溯问题,实际上就是一个决策树的遍历过程。

解决 3 个问题: 1、路径:也就是已经做出的选择。

2、选择列表:也就是你当前可以做的选择。

3、结束条件:也就是到达决策树底层,无法再做选择的条件。

1.2.2  程序算法

八皇后问题是栈应用的另一个典型例子。在此问题中我用到栈的数据结构来实现回溯法,递归到底部然后回溯到保存之前信息的栈空间,然后执行pollLast的语句,取出棋子。假如有一行的每一列都放不下符合规范的棋子,那么for循环结束后就会自动返回之前的栈空间;递归中每一层,也就是每次进入一个方法体后我都会创建一个新的栈空间。

这个程序的回溯法巧妙在:每一行中可能有n列是符合条件的,但是如果最终的皇后数不到8的话,我们需要回溯,执行pollLast语句,然后继续之前栈空间的for循环,然后依次类推。一旦我们完成了八个皇后的放置的时候,此时一定是在第八行,我们继续执行for循环直到结束,然后回到上一个递归调用方法的帧栈继续执行for循环;直到棋子的所有摆放情况都已经遍历完了,最终我们的虚拟棋盘会变为空。

第二章  课设实现过程

2.1 实现所需算法

回溯算法(用递归的方法实现)

1、概念

回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到

某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不

通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所

有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜

索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果

肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。

否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所

有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用

来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的

方式系统地搜索问题的解的算法称为回溯法,它适用解一些组合数较大的问题。

2、基本思想

对于用回溯法求解的问题,首先要将问题进行适当的转化,得出状态空间树。

这棵树的每条完整路径都代表了一种解的可能。通过深度优先搜索这棵树,枚举

每种可能的解的情况;从而得出结果。但是,回溯法中通过构造约束函数,可以

大大提升程序率,因为在深度优先搜索的过程中,不断的将每个解(并不一定是

完整的,事实上这也就是构造约束函数的意义所在)与约束函数进行对照从而删

除一些不可能的解,这样就不必继续把解的剩余部分列出从而节省部分时间。

回溯法中,首先需要明确下面三个概念:

(1)约束函数:约束函数是根据题意定出的。通过描述合法解的一般特征用于去 除不合法的解,从而避免继续搜索出这个不合法解的剩余部分。因此,约束函数是对于任何状态空间树上的节点都有效、等价的。

(2)状态空间树:状态空间树是一个对所有解的图形描述。树上的每个子节点的解都只有一个部分与父节点同。

(3)扩展节点、活结点、死结点:所谓扩展节点,就是当前正在求出它的子节点 的节点,在 DFS 中,只允许有一个扩展节点。活结点就是通过与约束函数的对照, 节点本身和其父节点均满足约束函数要求的节点;死结点反之。由此很容易知道 死结点是不必求出其子节点的(没有意义)。

3、解题步骤

(1)描述解的形式,定义一个解空间,它包含问题的所有解,这一步主要明确问 题的解空间树。

(2)构造状态空间树。

(3)构造约束函数(用于杀死节点)。然后就要通过 DFS 思想完成回溯,具体流程如下:

(1)设置初始化的方案(给变量赋初值,读入已知数据等)。

(2)变换方式去试探,若全部试完则转(7)。

(3)判断此法是否成功(通过约束函数),不成功则转(2)。

(4)试探成功则前进一步再试探。

(5)正确方案还未找到则转(2)。

(6)已找到一种方案则记录并打印。

(7)退回一步(回溯),若未退到头则转(2)。

(8)已退到头则结束或打印无解

2.2 绘制程序框图

2.3运行程序截图

新方法和新思路

回溯法解决八皇后问题的过程中,并不需要记录整棵“搜索树”,而只需记录从初始状态到当前状态的一条搜索路径,是“线性链状”的,其最大优点是占用空间少。

利用WindowBuider进行八皇后问题的GUI动态演示。利用鼠标监听器MouseListener监听按钮的动作,并用Graphics类进行绘制GUI界面。

在进行八皇后问题求解的时候,我使用了链表进行操作。构造了Location类对链表进行操作,在该类中有棋子的x和y坐标的属性,并重写了toString(该方法在testArea中打印一个合适的被放置的棋子的具体位置)。当有合适棋子放置的时候调用offer方法,要移除棋子的时候调用pollLast方法。

使用ImageIcon 加载棋子 的图片,并调用该类的paintIcon方法绘制图片,调用Graphics类的clearRect方法清除图片

程序代码

https://download.csdn.net/download/m0_54570435/87711569

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X-MTing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值