A*寻路算法的优化与改进

【转载】http://blog.csdn.net/silangquan/article/details/40516625

提要

通过对上一篇 A*寻路算法的学习,我们对A*寻路应该有一定的了解了,但实际应用中,需要对算法进行一些改进和优化。

Iterative Deepening Depth-first search- 迭代深化深度优先搜索

在深度优先搜索中一个比较坑爹情形就是在搜索树的一枝上没有要搜的结果,但是却非常深,甚至深不见底,这样就根本搜索不到结果。为了防止这种情况出现,就出现了Iterative Deepening的思想。


迭代深化搜索(Iterative deepening search, IDS)或者(迭代深化深度优先搜索,Iterative deepening depth-first search)是一种常用的搜索机制,经常使用在深度优先搜索中.通过逐渐地提高深度限制搜索(Depth-limited search)的深度限制(depth limit)——从1开始,然后2,一直到找到目标结点位置为止——迭代深化搜索能够找出最好的深度限制.深度限制搜索指的是在深度优先搜索中,引入深度限制limit,如果从根结点出发到结点N的深度为limit,那么N被当做没有子结点的叶结点那样处理.

找一棵树来具体看一下。


需要找ee节点。

首先把深度限制设置为1,则要搜索的树为


对其进行深度优先搜索,没搜到,增加深度限制为2.


进行DFS还是没搜索到,继续增加深度限制到3.


进行DFS,Bingo,找到。

和直接用DFS一样啊,看起来傻傻的? No!

这个方法首先规避了最开始说的DFS深度的问题,相对于BFS一般需要存储产生的所有结点,占的存储空间要比深度优先大得多,ID-DFS它的内存占用又少很多。再来看看时间复杂度.


迭代深化搜索也许看起来比较浪费时间,因为状态有可能被多次产生.但是事实并非如此,因为大多数的结点处在底层,而底层结点的搜索次数很少.对于一个深度为d,分支因子为b的树,.最多需要搜索的结点个数为:

故此迭代深化搜索的时间复杂度和深度优先搜索的一样是O( bk

So… 这个算法是两种搜索方法的折中,BFS能搜索到的,它就一定能搜到,而且不用那么多的空间,只需牺牲一点点的时间(相同的节点可能要访问很多次)。


下面是一个一般一些的例子,包含了三种算法的对比。




Iterative Deepening A*

迭代延伸A*可以简写成IDA*,用的也是迭代延伸的思想,这里的bounding就不再是树的深度了,而是 f(n) 的值。

首先还是从s出发,,bounding的值就是f(s),接下来就是从s进行深度优先搜索,f() 值大约阈值的全部不管,没有找到的话就增大阈值,再进行DFS….直到最后找到最终的节点。


很明显,IDA*用深度优先搜索替代了Open List 和Close List, 减少了内存上的开销,也少了List维护的花费。虽然每次搜索都要从头开始,这看上去一次又一次去搜索同样的节点有点不合理,但是这个代价远远低于原版本中维护Open List和Close List. 


边缘搜索A*

A*算法最大的性能问题就是Open List和Close List的维护,IDA*最大的问题就是无法记忆维护历史,会重复搜寻节点,一个新的寻路算法 - 边缘搜索A*,A*和IDA*的折中。

它维护了两个List,Now和Later来记录搜索的边缘点,同时用IDA*的思想来推进,具体看一下伪代码。

  1. now - linked list of search nodes, list order determines order of evaluation  
  2. later - linked list of search nodes  
  3. root - start node  
  4. threshold = root’s g()  
  5. push root into now  
  6.   
  7. while now not empty  
  8.     for each node in now  
  9.         if node == goal  
  10.             stop  
  11.         if node’s f() > threshold  
  12.             push node onto end of later  
  13.         else  
  14.             insert children of node into now behind node  
  15.           
  16.         remove node from now and discard  
  17.           
  18.     push later onto now, clear later  
  19.     set threshold = minimum g() found that is higher than current threshold  
now - linked list of search nodes, list order determines order of evaluation
later - linked list of search nodes
root - start node
threshold = root's g()
push root into now

while now not empty
    for each node in now
        if node == goal
            stop
        if node's f() > threshold
            push node onto end of later
        else
            insert children of node into now behind node

        remove node from now and discard

    push later onto now, clear later
    set threshold = minimum g() found that is higher than current threshold

now中存放的是当先需要被评估的节点,later中存放的是下一次将要评估的节点。

这个过程以比较弱的排序来维护列表,并且以像IDA*的深度优先的方式来有效地扩展节点,如果一次完成遍历now之后没有找到目标,则增加threshold值,later列表变成now列表,搜索又从now列表的顶点开始。虽然搜索过程需要now和later列表的维护,却没有排序的开销,而且内存的消耗比A*少太多。


参考

Artificial Intelligence 3.7 - http://www.cs.ubc.ca/~poole/aibook/html/ArtInt_62.html

Iterative Deepening - http://www.comp.lancs.ac.uk/computing/research/aai-aied/people/paulb/old243prolog/subsection3_6_4.html

Game Programming Gems 3.7

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值