关于A的介绍,可以移步到这里。
本文参考[Amit`s A Pages](http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html)。
在 A 的介绍中,我们提到A是通过计算节点的代价成本来寻找当前的最佳路径。而A优于其他搜索算法的原因就是A的启发函数。
启发函数计算的是从当前节点到目标节点的一个预估成本。其实也就是从当前位置到目标位置的移动距离,预估的距离越准确,A搜索的路径就越优,因此启发函数
的结果对A路径规划的结果也起了重要的影响。
| 启发函数计算值 | 函数 | 搜索结果 |
|---|---|---|
| A*算法退化成Dijkstra | 仅能保证可以找到一条最优路径 | |
| 保证能找到一条最优路径 | ||
| 最优状态,仅寻找最佳路径,不扩展别的任何节点 | 保证能找到一条最优路径,而且运算速度很快 | |
| 容易扩展到其他节点 | 不能保证找到一条最佳路径,但是运算最快 | |
| 此时只有 |
因此,我们需要根据不同的使用场景,来设计不同的启发函数。如果你想要有更快的运行速度,那就设计一个更大的启发函数,但是你就得牺牲结果,A找到的可能就不是一条最短的路径;如果你想要最短的路径,那就设计一个小点的启发函数,但是你就得牺牲运行时间。最佳的效果是无限的逼近实际的代价,这样A就既能得到一个最佳路径,又不会浪费过多时间。
栅格地图中的启发函数
在栅格地图中,有几个广为人知的启发函数可以使用。
在栅格地图中,不同的移动方式应该匹配不同的启发函数:
- 如果移动方向是四邻域的,那应该使用曼哈顿距离去计算启发函数;
- 如果移动方向是八邻域的,那应该使用对角线距离去计算启发函数;
- 如果是在正方形网格上任意方向移动的,则可能需要欧几里得距离,但是如果在网格上找路径,但不在网格上移动,那就得需要考虑其他的计算方式了;
- 如果是在六边形网格上移动,具有6个方向,则可以用适合六边形网格的曼哈顿距离;
在计算的时候,必须保证和
计算的单位是一致的。例如,如果是以米为单位进行测量的,距离为3个方格,每个方格10米,则启发函数的预估成本应该是
米。如果是以分钟为单位进行测量的,距离3个方格,每个方格移动需要5分钟,则启发函数的预估成本应该是
分钟。
曼哈顿距离
欧几里得距离标明两个点在标准的坐标系上的绝对轴的距离总和,即:

曼哈顿距离的计算方式适用于只有四个方向可移动的场景中。即,你的移动方向是四邻域的,那么曼哈顿距离是最佳的选择。
D 表示的是移动方块的权重,你可以设置它为10或者1都可以。
对角线距离
如果你的地图允许对角线移动,则需要用一个不同的启发函数,对角线距离。
对角线距离又称为切比雪夫距离(wiki),表示两个点之间的距离定义为其各坐标数差值的最大值。
假设直线移动和对角线移动的代价成本都是D,则

但是,如果对角线运动的代价不是,则是类似于
,那么,更准确的对角线距离计算公式应该是:

欧几里得距离
如果是可以沿任意角度移动(而不是网格方向),那么也许可以使用直线距离。

使用欧几里得距离计算的距离会比曼哈顿或者对角线距离还短,但是还是可以得到一个最短路径,只是将耗费更多的时间。
平方后的欧几里得距离
也有通过对距离的平方来避开欧几里得距离中的平方根计算,为了机器计算时的运算时间。

但是不要这么做,这会明显的导致衡量单位的问题。此时的计算将会使得的结果恒大于
,将会导致因为启发式函数评估值过高而停止。对于较长的距离,这将到接近
的极值,而
并不影响,而A*将退化成BFS。
Breaking Ties(打破平局)
在一次的搜索过程中,可能会有存在多个相同的,他们都会被搜索。因此出现了在搜索对比中的平局的局面。
解决这个问题,可以为启发函数增加一个附加值。附加值对于结点必须是确定性的(也就是说,不能是随机数),而且它必须让的值体现差异。
在上增加一个衡量单位 p 值。
选择因子p使得p < 移动一步(step)的最小代价的最长路径长度
假设不希望路径超过1000步,可以使 p = 1 / 1000
添加这个附加值的结果是,A比以前搜索的结点更少了
当存在障碍物时,当然仍要在他们周围寻找路径,但是当越过障碍物之后,A搜素的区域将非常少。
当然,对于要打破局面的做法,还有一个更直接的方法。
如果对于两个相同的结果,那么可以对比
的值,以此来打破这个平局(breaking ties)。
还有另外一种方法,就是在启发式函数上添加一个确定性的随机数,这个随机数时计算坐标的哈希值。
第四种解决这个问题的方法。
对于启发式函数的计算,选择从初始点到目标点的连线。
对于这样的方法,A在选择路径时会稍微更倾向于从初始点到目标点的直线,当没有障碍物时,A不仅搜索的区域很少,而且它找到的路径看起来也非常的棒。
然而,因为这种方法是更倾向于起点到终点的直线连接,因此当出现了障碍物时,就会出现很奇怪的现象。
