计算最短路径的A* 算法简介

      

A*算法是到目前为止最快的一种计算最短路径的算法,但它一种‘较优’算法,即它一般只能找到较优解,而非最优解,但由于其高效性,使其在实时系统、人工智能等方面应用极其广泛。

A*算法结合了启发式方法(这种方法通过充分利用图给出的信息来动态地作出决定而使搜索次数大大降低)和形式化方法(这种方法不利用图给出的信息,而仅通过数学的形式分析,如Dijkstra算法)。它通过一个估价函数(Heuristic Functionf(h)来估计图中的当前点p到终点的距离(带权值),并由此决定它的搜索方向,当这条路径失败时,它会尝试其它路径。

因而我们可以发现,A*算法成功与否的关键在于估价函数的正确选择,从理论上说,一个完全正确的估价函数是可以非常迅速地得到问题的正确解答,但一般完全正确的估价函数是得不到的,因而A*算法不能保证它每次都得到正确解答。一个不理想的估价函数可能会使它工作得很慢,甚至会给出错误的解答。

为了提高解答的正确性,我们可以适当地降低估价函数的值,从而使之进行更多的搜索,但这是以降低它的速度为代价的,因而我们可以根据实际对解答的速度和正确性的要求而设计出不同的方案,使之更具弹性。

众所周知,对图的表示可以采用数组或链表,而且这些表示法也各也优缺点,数组可以方便地实现对其中某个元素的存取,但插入和删除操作却很困难,而链表则利于插入和删除,但对某个特定元素的定位却需借助于搜索。而A*算法则需要快速插入和删除所求得的最优值以及可以对当前结点以下结点的操作,因而数组或链表都显得太通用了,用来实现A*算法会使速度有所降低。要实现这些,可以通过二分树、跳转表等数据结构来实现,我采用的是简单而高效的带优先权的堆栈,经实验表明,一个1000个结点的图,插入而且移动一个排序的链表平均需500次比较和2次移动;未排序的链表平均需1000次比较和2次移动;而堆仅需10次比较和10次移动。需要指出的是,当结点数n大于10000时,堆将不再是正确的选择,但这足已满足我们一般的要求。

还有一种更好的方法是Hot Queues,而且这种方法还可应用于Dijkstra算法以降低其复杂度。当我们移动估价函数值为f的结点时,我们插入值为f+δ(δ<=C)(若δ>=0将意味着估价函数是有效的,反之亦然),常量C为从一个结点到相邻结点的权的最大改变。同时我们用一些“容器”来保存估价函数值的子集(这正如o(n)的排序算法的思想),例如,当有10个“容器”时,堆将平均只包含1/10的估价值。因而这将比用堆更为有效。

     估价函数(Heuristic Function

估价函数的正确选取将直接关系到A*算法的成功与否,而函数的确定却与实际情形有着密切的关系。在本文中,仅对网格状地图的估价函数作部分讨论,而在其它情形中,需要作不同的分析,但至少估价函数应为连续函数。

a.      Manhattan Distance

这是一种标准的估价函数,

h(A) = 10 * (abs(A.x-goal.x) + abs(A.y-goal.y))

b.      Diagonal Distance

如果在地图上允许作斜线方向的运动,则Mahattan Distance修正为Diagonal Distance

h(A) = max(abs(A.x-goal.x), abs(A.y-goal.y))

 

     估价函数的判优

一般情形下,我们只需对估价函数的值进行比较而取其大者即可,但在几个结点的估价函数值相同的情形下,我们需要采取一定的策略来决定这几者谁更优,从而避免对多个点的搜索。从而如下代码可实现之:

double dx1 = currentX - goalX;

double dy1 = currentY - goalY;

double dx2 = startX - goalX;

double dy2 = startY - goalY;

cross = dx1*dy2 - dx2*dy1;

if( cross<0 ) cross = -cross;

... add cross*0.001 to the heuristic ...

这段代码计算始点、当前点和终点的矢量积,从而可以判断这三点是否共线(或近似共线),这样不同点间即使有微小的差别也会被放大,从而更利于判断。

     改进的A*算法

a.      Beam Search

A*算法中需要保留所有的结点,这将使得时间和空间的消耗都很大,而Beam Search方法对结点数作出限期,当结点数过多时,它会将一些不()可能为最优的点排除,从而降低时间和空间的要求,但需要说明的是,由于在排除结点后需对结点排序,当排序的工作量大于排除点后所节省的工作量,则该方法无意义。

b.      Iterative deepening

这是一种在人工智能中常使用的方法,它首先产生一近似值,然后对它进行修正而逐步接近最优解。这其实在一种博奕算法的变形。

c.      Dynamic weighting

这种算法是基于这样的考虑,即在搜索初期以速度优先,在搜索后期以准确度优先(这可通过对搜索初、后期赋予不同的权值来实现)。即:

f(p) = g(p) + w(p) * h(p)

d.      Bidirectional search

这种算法从起点和终点同时应用A*算法,直到有结点相遇。其缺点在于复杂度太大,一般仅用于复杂的图形。

e.      Hierarchical A*

这种算法思想是将搜索过程化,对每个简单过程求解从而得全局较优解。正如当我们到另一城市时,可分解为从家里“搜索”一条路径至车站,再从车站“搜索”一条路径到另一城市,当我们从家里出发时,需要考虑的是怎样尽快地到达车站,而不是怎样尽快地到另一城市。

f.      Dynamic A*(D*)

这种算法主要用于人工智能和机器人技术。由于A*算法一开始要求获得全部信息,而这在实际中有时是不可能的,而D*算法就是在假定信息不完整的前提下应用A*算法,但它会随着得到信息的增多而不断改进结果,这就决定了它对空间的要求相当高,因为它需要保留以前的所有获得信息及运算情形。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值