A*算法之旅之初识A*算法(一)

A算法之旅之初识A算法(一)

声明在前:通过最近一段时间对A*算法的学习,对这个算法有了一定的了解,在此总结以备后用。疏漏之处,在所难免,欢迎批评指正。


对于仅仅想了解A*算法的朋友,以下有三篇文章:
A* Pathfinding for Beginer
A* Pathfinding for Beginer 译文 有少许指代不明
理解A*算法具体过程 给出的代码有一点疏漏,后文会指出,如果是本人错了,也希望大家指正。


下面是深入学习A算法,在此感谢一篇优秀的文章,本人的学习大部分都是通过它而来,"堪称最好的A算法讲解",英文论著,有条件的朋友不妨去看一下,一定有不少收获。本文中大多数图片都引用自它。以下是相关链接:最好的A算法-英文版,对于英语不是太好的朋友,这里有一篇对于上文的翻译,不过翻译的不够全面,很多部分都跳过了,不过还是很有帮助的:最好的A算法-中文版(部分)


##简介:
先给出一个权威的定义:A算法,A(A-Star)算法是一种静态路网中求解最短路最有效的方法。通俗的来讲,就是给定一个图,里面有很多点,求解从起始点(start)到终止点(end)的最短路径。


###算法引入:
A*算法相对于一般的算法的优越性在于它的函数构建上,它有一个独特的估价函数,称之为f(n),函数形式如下:
f(n) = g(n) + h(n)
函数说明:
g(n) 是从start 点开始到当前节点current的耗费函数(cost,此处耗费是广义的,可以理解为是距离、时间等)。

h(n) 是从当前节点current到end点的启发函数(heuristic),它反映的是从current到end的即将可能产生的耗费,实际上它是未知的,我们只能大致估测出它的值,因此也就不难理解为什么是启发函数了,它启发我们后续可能的结果,因此让我们判断更准确高效。

f(n)就是估价函数了,它能给我们这个节点的可取度,文章论述中 以 更小 优先处理,如果某个节点f(n)小于另一个节点的f(n),就说明前一个节点的可取度更高,我们会优先考察它。

好了,我们继续
普通的节点依次考察,逐层扩散,如下图:
dijkstra

此图红点为start点,蓝点为end点,而所有的浅蓝点代表红点寻路过程中考察过的点,由此图我们可以很轻易地看出,浅蓝色点从红点开始,为寻找一条路径逐层扩散,它考察了很多根本不必要的点,比如整个左侧的点,这就造成了他效率的下降。比较有代表性的就是dijkstra算法:
这里简要介绍一下该算法思想,将start点加入一个队列,考察队列第一个点,删除该点,依次将该点的周围点加入一个队列,进行下一步的循环考察,删点,加点,考察。。。直到队列中没有下一个点(证明该图中没有可行路径),或者end点被加入该队列,说明找到可行路径。
从算法中也很轻易地看出,该方法是扩散式的,没有明确的目的,因此造成时间上的开销很大。这种情况对应的就是h(n)=0的情况,启发函数没有给我们任何信息,因此只能盲目的遍历。

如果只考虑目标会不会更好?比较经典的有best-first-search算法,如图:
best-first-search

此时假如我们的节点知道通过哪个节点会使得目标路径更近,它就会暂时放弃那些看起来会使目标路径更远的点,直到当前节点可能到达的路径均被证明不可行。通过这个我们就可以看出来,它的效率比上文中的dijkstra算法要高,因为它使用了精确的启发函数(启发函数一般不精确),让节点的考察趋向于它所以为的接近。这就是所谓的贪心策略了:总是找目前看起来最好的,不考虑已经产生耗费。从上述函数的角度讲:就是g(n) = 0的情况。从上图中看出,离蓝点越近,点的颜色越黑,代表它的启发值越近。

这听起来很不错,它的效率已经可以让我们可以接受了。但是。。。假如路径中存在障碍呢?看下图:
best-first-search-trap
这就是一个陷阱,在搜索点逐渐向目标点靠近时,它无法预测前方可能的情况(可能是障碍:耗费 无穷大,不可行,也可能是相比周围点耗费比较大的点,虽然可行,但是不如绕个弯更优),因此也就导致了多次的搜索死点(对最终路径毫无帮助的点),而且它甚至不能保证最后的路径是最短的!

而与之对应的是dijkstra算法:
dijkstra-trap
该算法虽然比BFS(best-first-search)多搜索了一倍多的点,但是,它最终给出了一条最短路径。

小结:能否将二者优点结合起来呢?因此也就有了A算法,它同时考虑g(n) 和 h(n),既考虑已经产生的耗费cost,又考虑可能产生的耗费。而与BFS稍有不同的是,BFS中通常每一个点的cost都是确定的,而我们这里的启发函数h(n)是一个大概取值,不一定精确。同样,A基于无法保证最佳解的启发式方法,A*却能保证找到一条最短路径。


###A*算法:
在此仅以游戏中的寻路问题讨论A算法,A是路径搜索中最受欢迎的算法,因为它的灵活和可扩展,便于用于各种情况。
和dijkstra相同,它能给出最短路径;和BFS相同,它能用启发函数导向自己快速接近end点。
在简单情况下,它和BFS一样快:
a-star

在障碍例子中,它和dijkstra都能给出最短路径<但不是最优解,所谓的最优解是指只考察最短路径周围的点,忽略非必要的点>:

a-star-trap
算法关键点就如上文所说,它将两个算法的优点结合起来,同时考虑g(n) 和 h(n),构成独特的估价函数 f(n) = g(n) + h(n)。
每次在主循环中寻找下一个可行的节点时,既考虑当前已产生的耗费–>从start到current的cost,又考虑接下来可能要产生的耗费–>从current到end的cost,选取二者和最小的节点进行考察。

以下给出该算法思想的当前伪代码(待细化):

将 start 加入 一个空队列中
while(队列不为空)
    考察队列中最优的元素;
    将该元素移出队列;
    添加元素邻近元素入队列;
    if(队列中有end)
        路径找到;结束;
未找到路径;结束;

好了,第一篇到这里就结束了(还有一些坑没填呢),有兴趣的朋友可以继续往下看第二篇:)A算法之旅之初识A算法(二)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值