A*算法实现

A*算法实现

一、 算法思想

      搜索中利用启发式信息,对当前未扩展结点根据设定的估价函数值选取离目标最近的结点进行扩展,从而缩小搜索空间,更快的得到最优解,提高效率。

二、 启发函数

1、 不在位数码个数
      启发函数h ( n )为当前结点不在位的数码个数。由于一次只能移动一个数字位,因此h ( n ) <= h * ( n ), 同时有h ( t ) = 0  而且对于结点m和n (n 是m的子结点) 有h ( m ) – h ( n ) <= 1 = Cost ( m, n )  即该启发函数满足单调限制条件,只要扩展到某个结点,就找到了从初始结点到达该结点的最优路径。

2、 每个数字位与对应目标数字位间距离和
    进一步考虑当前结点与目标结点的距离信息,令启发函数h ( n )为当前8个数字位与目标结点对应数字位距离和(不考虑中间路径), 同样满足h ( n ) <= h * ( n ), 且对于目标有 h ( t ) = 0,对于结点m和n (n 是m的子结点) 有h ( m ) – h ( n ) <= 1 = Cost ( m, n ) 满足单调限制条件。

三、 具体实现

1、 结点编码
      对于8数码问题,每个结点有8个数字和一个空格,可以将空格看成0,那么一共有9个数字,32位的int可以表示2* 109 ,可以用一个整数表示一个结点对应的信息。计算一个整数中0(即空格)的位置比较耗时间,用一个整数存储当前结点0的位置,还要存储对应的 g , h 值以及该结点由哪个结点扩展来的信息。

2、 open表的数据结构表示
      考虑对open表的操作,每次需要得到所有待扩展结点中 f 值最小的那个结点,用堆进行实现,可以达到O ( log ( heapSize ) ) 时间复杂度。

3、closed表的数据结构表示
      closed表存储已扩展的结点间的扩展关系,主要用于输出路径。考虑结点扩展的操作,设待扩展的结点为m,由它扩展生成的结点为n1, n2, … 。结点m扩展完成后被放到closed表中,放入后它在closed表中位置不发生变化,可以将n1, n2, …的前驱结点置为m在closed表中的位置,当n1, n2, ..中有结点设为n1被扩展放入closed表时,n1的前驱刚好已经存储好。下面说明closed表中任意一个结点都存储有它的前驱结点的信息,考虑closed表中任意一个结点,如果它是初始结点,它没有前驱结点,如果不是根结点,扩展该结点时它的前驱结点已经记录。从而在closed表中形成扩展关系的树状结构。因为只需要前驱结点的下标位置,可以用数组实现,每个结点记录整数表示的8数码格局和它的前驱结点的下标,输出路径时,根据前驱结点形成到达根结点的链条,递归输出即可。

4、解决结点重复扩展问题
      对于一个结点有多种方式到达该结点,这样就可能多次将它加入open表中,而启发函数满足单调限制条件,后来达到该结点的路径不再是更优的,可以不予考虑。扩展某结点时先看该结点是否已经扩展过,如果扩展过则略过。实现的可以线形遍历closed表,但效率不高时间复杂度为O ( closedSize),考虑每个结点可以用一个整数标识,用二叉平衡查找树可以得到更好的时间复杂度O ( log (closedSize) ) ,程序中用基于红黑树思想的set实现。

四、 对比程序

      为对比测试时间,实现了宽度优先方法求解8数码问题和两种启发函数的A*算法。宽度优先是一种盲目搜索方法,没有深入挖掘问题的可利用信息,或者说h ( n ) = 0。搜索扩展结点时,只是根据层数优先根据扩展结点的先后顺序选择当前要扩展的结点,搜索空间大,耗时比较长。而启发函数好坏将直接影响A*算法性能。

五、 输入输出

      程序采用文本输入输出,输入文件为astar.in,A*算法第一种启发函数输出文件为astar1.out,第二个启发函数输出为astar2.out,宽度优先算法输出为bfs.out,可以用记事本打开。
输入格式为一个测试用例由两个中间由一空行隔开的8数码格局组成,输出为对应测试用例的走法路径及相关统计信息,程序假定输入数据符合要求,未做检查。

六、 测试结果

      测试用例最后一个需要30步才能得到结果,数据规模较大,宽度优先算法和第一种启发函数A*算法需要几秒才能运行得出结果,第二种算法非常快即得到结果。以下数据为VC++6.0编译得到的结果,VC++6.0对标准C++中STL支持不好,利用g++进行编译可以极大的缩短时间(经测试所有测试用例均在1秒内得出正确结果)。

宽度优先算法:

输入数据编号

步数

扩展结点数

生成结点数

搜索用时(毫秒)

1

5

36

65

15

2

18

23486

34961

1141

3

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值