首页 > 代码库 > A*算法在求最短路上的应用
A*算法在求最短路上的应用
在学习A*算法之前,首先回忆一下一个非常经典的单源最短路算法Dijkstra
1)维护一个表dist,储存当前求出的各点到S的距离
2)取出dist表中的最小值(显然这个过程是可以用堆优化的),并用该最小值对其他各点的dist值做松弛更新
3)重复2)过程,直到取出的最小值对应节点为T
这里其实无形中也用到了接下来即将讲到的open表和close表的概念
open表储存的是待扩展的点,一定程度上对应Dijkstra中的list
close表中储存的是已经扩展过的点,以防出现重复
那么接下来谈谈A*算法在Dijkstra算法的基础上做了什么
让我们回忆一下,多源最短路算法求出来的结果是什么,其实远远超出了我们的所需,我们最终得到的dist,是S到所有点的最短路距离。
然而当我们只需要S到T的最短路时,我们为什么需要去扩展那些我们没有必要扩展的点,哪怕它对应当前最小的dist?最小的dist又不一定会对S到T的最短路求解有必然的帮助。
所以我们需要引入一个评估函数
f(p)=h(p)+g(p)
其中, g(p)表示S到p的实际最短距离,h(p)表示p到T的估计距离
g(p)是容易解决的,因为当你对p开始进行评估时,说明它的dist是当前最小,毫无疑问它当前的dist就是g(p)
h(p)取决于问题设定,视情况而定,一般设为p到T的曼哈顿距离或欧几里得距离(栅格化地图中前者更常用)
当你发现,f(p)甚至比当前T的dist还要大,那么根本没有必要对p进行拓展。假装自己扩展过了,将p打入close表的冷宫吧!
这里有一个前提,h(p)估算出的距离必须小于或等于p到T的实际最短距离,这一点比较显然,却是A*算法优化的基础(其实就是一个很基本的搜索剪枝的思想)
先给出A*的流程
1)将起点S放入open表中
2)对open表中dist最小的相邻节点进行评估,评估不合格则直接放入close表(孩子你没救了,洗洗睡吧
否则进行拓展,将该点放入open表待扩展(少侠有前途,我钦点看好你
扩展以后的点,也放入close表(该干的都干了,可以卸甲归田了
3)close表中出现了T!那啥也别说了,算法结束
如果需要记录路径的话,只要记录一下某个点是从哪个点扩展而来的,记录一下父节点即可。
最后思考一下为什么A*算法中这么强调open表
因为A*算法利用评估函数力求缩减扩展的次数,但Dijkstra一开始就是冲着把所有点扩展一遍去的,因而不需要open表(因为它的open表默认包含了所有点)
但A*则是在评估以后再判断是否放入open表中扩展,这就是优化所在。
A*算法在求最短路上的应用