- 1.
- 2.
- 3.
h(n) = h'(n, w1) + distance(w1, w2), h'(w2, goal)
网格地图中的启发式算法
在网格地图中,有一些众所周知的启发式函数计算方法:
1.曼哈顿距离2.对角线距离3.欧几里得距离4.欧几里德距离平方- 1.
- 2.
- 3.
- 4.
标准的启发式函数是曼哈顿距离(Manhattan distance) 。考虑代价函数并找到从一个位置移动到邻近位置的最小代价D 。因此,h是曼哈顿距离的D倍:
``` H(n) = D* (abs ( n.x – goal.x ) + abs ( n.y – goal.y ) ) ```- 1.

文章插图
对角线距离
如果在地图中允许对角运动那么需要考虑对角线距离 。(4 east, 4 north)的曼哈顿距离将变成8D 。然而 , 可以简单地移动(4 northeast)代替,所以启发函数应该是4D 。这个函数使用对角线 , 假设直线和对角线的代价都是D:
H(n) = D * max(abs(n.x - goal.x), abs(n.y - goal.y))- 1.

文章插图
如果对角线运动的代价不是D,但类似于D2 = sqrt(2) * D , 则准确的计算方法如下:
h_diagonal(n) = min(abs(n.x - goal.x), abs(n.y - goal.y))h_straight(n) = (abs(n.x - goal.x) + abs(n.y - goal.y))H(n) = D2* h_diagonal(n) + D* (h_straight(n) - 2 *h_diagonal(n)))- 1.
- 2.
- 3.
- 4.
- 5.
欧几里德距离
如果单位可以沿着任意角度移动(而不是网格方向),那么应该使用直线距离:
``` H(n) = D* sqrt((n.x-goal.x)^2 + (n.y-goal.y)^2) ```- 1.

文章插图
欧几里德距离平方
还有一个方法是 , 使用距离的平方替代距离,避免进行平方根开方运算,从而减少计算消耗:
``` H(n) = D* ((n.x-goal.x)^2 + (n.y-goal.y)^2) ```- 1.

文章插图
启发函数的启发因子
导致A搜索低性能的另外一个原因是启发函数的启发因子 。当某些路径具有相同的f值的时候,它们都会被探索,比较函数无法打破比较平衡点,尽管我们这时候只需要搜索其中的一条,下图为没有添加启发因子的效果:

文章插图
为了解决这个问题,我们可以为启发函数添加一个较小的启发因子 。启发因子对于每个结点必须是确定的唯一的 , 而且它必须让f值体现区别 。因为A将会对f值进行堆排序,让f值不同,意味着只有一个f值会被检测 。
一种添加启发因子的方式是稍微改变h的衡量单位 。如果我们减少衡量单位,那么当我们朝着目标移动的时候f将逐渐增加 。很不幸 , 这意味着A倾向于扩展到靠近初始点的结点,而不是靠近目标的结点 。我们可以稍微的微调h的衡量单位(甚至是0.1%),A就会倾向于扩展到靠近目标的结点 。
