A heuristic h(n) is consistent if, for every node n and every successor n' of generated by any action a, the estimated cost if reaching the goal from n is no greater than the step cost of getting to n' plus the estimated cost of reaching the goal from n': h(n) <= c(n,a,n') + h(n')
一般最常用的启发式是Manhattan距离或者是直线距离,显然这样的启发式满足上面的条件。但是注意到如果A*算法要用在有权重的路径上而且没有先验的直线距离,这个启发式就比较难写了。不过这也是启发式的特点,所谓启发式就是充分利用问题中的先验信息,这样的启发式会使算法快速而准确。如果问题只有少的可怜的假设,比如编一个可以在有权重路径上工作的A*算法,这样就不能对输入数据做任何假设,使得启发式难于构建或者要耗费额外的计算量。在这种情况下,A*算法就会比较慢了,因为A*算法是一个很依赖启发式的算法。
如果要写一个可以工作在有权重路径上的A*,启发式可以这样写,先求得所有路径权重的平均值,然后搜索中间节点n和目标节点g之间有多少个节点(这个搜索同样使用A*,但是注意必须除去图中所有障碍以及把所有权重全部设为相同的值),那么h(n)为平均值乘以节点个数。要注意两点:第一,计算节点个数实际上是n, g两点之间的最短距离的一个简化。因为这一步是启发式,所以要计算量要少而且要提供足够有用的信息。第二,这样的计算方法很显然不符合A*算法最优的条件,所以使用这个启发式不保证得到最优解。
A*算法虽然是使用的最普遍的寻路算法,但是针对一些特定的地图,其效率还有提高的余地。在一些2D游戏中,地图上往往会有一些很大的障碍物,比如小山,湖泊之类。在使用Manhattan启发式的A*算法在这样的地图上搜索的时候, 如果起点到终点之间有大的障碍,那么A*算法必然会碰到此障碍并且回退许多步。如何使得A*算法在碰到此障碍之前就选择一条可以绕开障碍的路径呢?有两条:第一,判断终点与起点之间是否存在大的障碍,如果没有,那么使用A*。要做到这种判断必须先对地图进行一些初始化处理,假设地图是用矩阵表示,那么大障碍物所包含的矩阵元素需要有和小障碍不一样的值。比如小障碍的值为1,大障碍为2 。那么计算起点与终点之间的Manhattan路径是否有值为2的元素就可以做到这样的判断了。具体的方法和上面提到的方法一样,使用A*。如果计算得出路径中会遇到大障碍该怎么办呢?这就是第二点,需要对地图做一个比较复杂的预处理。我们把矩阵中每一个元素都赋予一个权重(不是路径的权重,是点的权重),使得在大障碍周围的那些点有较高的权重,这样的话在A*还没有碰到障碍之前就因为较高的权重而转向从而不会碰壁了。那么这些权重应该怎么设置才合理呢?蚁群算法是一个很好的选择(关于蚁群算法可以查阅相关资料),设置一定数量的蚂蚁在地图上行走一定时间,最后的权重和与此节点相关的所有路径上信息素成反比。也就是说蚂蚁经过的节点的次数越少,此节点权重越高。因为这是预处理,只要赋予了权重,在以后的搜索中都不用再做这样的计算,那么复杂度可以忽略。
以上只是一些初步的想法,还没有验证过。相关的一些参数也需要实验获得,比如权重的反比公式需要乘上多大的常数才合适