八数码问题
一.八数码问题
八数码问题也称为九宫问题。在 3×3 的棋盘,摆有八个棋子,每个棋子上标有 1 至 8 的某
一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到
空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成
目标状态的移动棋子步数最少的移动步骤。
所谓问题的一个状态就是棋子在棋盘上的一种摆法。棋子移动后,状态就会发生改变。解
八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。
八数码问题一般使用搜索法来解。
搜索法有广度优先搜索法、深度优先搜索法、A*算法等。这里通过用不同方法解八数码问
题来比较一下不同搜索法的效果。
二.搜索算法基类
1.八数码问题的状态表示
八数码问题的一个状态就是八个数字在棋盘上的一种放法。每个棋子用它上面所标的数字
表示,并用 0 表示空格,这样就可以将棋盘上棋子的一个状态存储在一个一维数组 p[9]中,
存储的顺序是从左上角开始,自左至右,从上到下。也可以用一个二维数组来存放。
2.结点
搜索算法中,问题的状态用结点描述。结点中除了描述状态的数组 p[9]外,还有一个父结
点指针 last,它记录了当前结点的父结点编号,如果一个结点 v 是从结点 u 经状态变化而产
生的,则结点 u 就是结点 v 的父结点,结点 v 的 last 记录的就是结点 u 的编号。在到达目标
结点后,通过 last 可以找出搜索的路径。
3.类的结构
在 C++中用类来表示结点,类将结点有关的数据操作封装在一起。
不同的搜索算法具有一定共性,也有各自的个性,因此这里将不同搜索算法的共有的数据
和功能封装在一个基类中,再通过继承方式实现不同的搜索算法。
4.结点扩展规则
搜索就是按照一定规则扩展已知结点,直到找到目标结点或所有结点都不能扩展为止。
八数码问题的结点扩展应当遵守棋子的移动规则。按照棋子移动的规则,每一次可以将一
个与空格相邻棋子移动到空格中,实际上可以看作是空格作相反移动。空格移动的方向可
以是右、下、左、上,当然不能移出边界。
棋子的位置,也就是保存状态的数组元素的下标。空格移动后,它的位置发生变化,在不
移出界时,空格向右、下、左和上移动后,新位置是原位置分别加上 1、3、-1、-3,如果
将空格向右、下、左和上移动分别用 0、1、2、3 表示,并将-3、3、-1、1 放在静态数组
d[4]中,空格位置用 spac 表示,那么空格向方向 i 移动后,它的位置变为 spac+d[i]。
空格移动所产生的状态变化,反映出来则是将数组 p[]中,0 的新位置处的数与 0 交换位置。
三.线性表
搜索法在搜索过程中,需要使用一个队列存储搜索的中间结点,为了在找到目标结点后,
能够找到从初始结点到目标结点的路径,需要保留所有搜索过的结点。
六.A*算法
1.启发式搜索
广度优先搜索和双向广度优先搜索都属于盲目搜索,这在状态空间不大的情况下是很合适
的算法,可是当状态空间十分庞大时,它们的效率实在太低,往往都是在搜索了大量无关
的状态结点后才碰到解答,甚至更本不能碰到解答。
搜索是一种试探性的查寻过程,为了减少搜索的盲目性引,增加试探的准确性,就要采用
评论10
最新资源