A*寻路算法(记忆版)

【转载】http://blog.youkuaiyun.com/jialeheyeshu/article/details/53105810
【转载】http://blog.youkuaiyun.com/silangquan/article/details/40400641

A*寻路算法介绍

A*算法的公式为:f(n)=g(n)+h(n),g(n)表示从起点到任意顶点n的实际距离,h(n)表示任意顶点n到目标顶点的估算距离。

对于函数h(n),估算距离常用的方法有:(常用曼哈顿距离)

  1. 曼哈顿距离:定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里德空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:|x1 - x2| + |y1 - y2|。
  2. 欧氏距离:是一个通常采用的距离定义,它是在m维空间中两个点之间的真实距离。在二维和三维空间中的欧氏距离的就是两点之间的距离。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的欧氏距离为: sqrt((x1-x2)^2+(y1-y2)^2 )。
  3. 切比雪夫距离:是两个向量之间各分量差值的最大值。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的切比雪夫距离为:max(|x1 - x2| , |y1 - y2|)。

A*算法最重要的就是维护两个列表,一个开启列表,一个关闭列表。

这里写图片描述

如上图方格中左下角:g(n),方格右下角:h(n),左上角:f(n)

上图是第一步:计算起点周围邻域的代价,跨越一条边是10,对角是14
把周围8个节点的G和H计算出来之后,计算F(就是G+H),这些节点的指针就指向当前的起始节点(如上图)。因为此时这几个邻域节点都没有在open列表中,于是就把这8个点加到open队列中,并且把当前节点也就是起始节点放到close中(也就是下次不再考虑了)。

第二步:从open队列中选择F最小的那个节点,此时可能有F相同的(这种情况就随便选个,不影响最短路径长度),我们选择40的那个,于是,把F=40的这个节点作为当前节点,如下图所示:(此时我们把40抹去了,因为之后会把这个节点放到close队列中,close队列中的点都是不考虑的,也只是为了描述方便,我们要的只是指针方向所形成的一条路径

这里写图片描述

第三步:把40的那个节点周围8邻域的节点计算完F后,放到open队列中,注意,此时障碍物的节点和已经放入close队列的节点不放,那么此时没有新节点加入进来,由于把上方涂抹了的那个节点当成当前节点,所以需要重新计算它的8邻域节点的G值和F值,(也就是它的上方那个,坐上方节点,下方节点,左下方节点,一个4个),此时G值的计算是这样的:比如计算上方那个(54 14 40),由于从原点到当前节点的G为10,从当前节点到上方节点的G值为10,所以10+10=20(也就是所到上方节点需要先从原点到这个点,然后在从这个点到上面那个点),但是新计算的G=20<14(节点原来的G值),所以上方节点的指针方向不变,(如果计算出来小于原来的值,那么就把上方节点的指针指向当前这个节点了)!!同样计算剩下的三个节点的G值,发现都大于原来的G值,所以节点指针方向没有做任何改变。

于是把当前节点放到close对列中,再从open队列中找F值最小的节点(此时队列中有7个节点)。于是把54那个节点(起始节点的右下方那个)当成当前节点,计算周围8邻域的G值和F值。但是障碍物下方的那个点不能加入计算,因为从当前节点到障碍物下方那个节点必须穿透墙角了!同样赋予节点父指针以及更新8邻域的G值和F值。

这里写图片描述

如此循环下去。。。当把起始节点(绿色那点)下方的那个节点当成当前节点的时候,注意它下方那个节点的父指针变化了,因为它原来的G值为28,但是通过当前节点的时候G能变小到20,所以对应的F也小了,那么,它的父指针就指向当前节点,表示这样走更近。

这里写图片描述

所以如此循环下去:不断从open队列中找最小的点作为当前节点并加入周围节点,不断更新周围8邻域的G和F,看看能不能比原来G值更小,如果小就更新,否则不更新,当前节点算完就放入close队列,然后再从open队列中找最小的点。。。。最后直到把终点加入open队列中,计算出指针指向就完事了。

所以最后的路径就是,从终点开始沿着父指针不断回缩,最后回到起始点,这样最短路径就找到了:
这里写图片描述

和其他单源最短路径算法的关系

A*算法:每次从OPEN列表中选择 f(n) 最小的节点将其加入CLOESE列表中,同时扩展相邻节点,可把OPEN列表看成一个优先队列,key值为 f(n),优先级最高的先出。
Dijkstra算法:每次从OPEN列表中选择 g(n) 最小的节点将其加入CLOSE列表中,同时扩展相邻节点,可把OPEN列表看成一个优先队列,key值为 g(n),优先级最高的先出。
DFS算法:每次从OPEN列表中选择最晚被加入的节点(栈的应用)将其加入CLOSE列表中,同时扩展相邻节点,可把OPEN列表看成一个栈,后进先出。
BFS算法:每次从OPENG列表中选择最早被加入的节点(队列的应用)将其加入CLOSE列表中,同时扩展相邻节点,可把OPEN列表看成一个队列,先进先出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值