A* 算法
A* 算法是求解最短路径的算法之一,其他的求解算法还有Dijkstra 算法、Bellman-ford 算法、SPFA 算法、Floyd算法等。
既然有了上面的那么多的算法,为什么还要设计A* 算法呢?
A* 算法较其他算法的不同就是它采用了启发式搜索的方式,一般算法采用的是直接搜索的方式。
相比与直接搜索方式启发式搜索肯定具备一定的优点,直接搜索方式是找到到达目的的所有路径,然后比较得出最短的路径。在搜索的过程中不做任何路径的处理。
而启发式搜索根据特定的启发函数,在搜索的过程中选择最优最优的路径,使得搜索的范围尽可能的小,这样就提高了搜索过程的效率。
A *算法基于 Dijkstra 算法和 Greed-Best-First-Search 算法
Dijkstra 算法
dilkstra 算法是比较常用的最短路径的求解算法。在该算法中维护着一个dis[]数组,表示愿节点到各个节点的最短距离。例如,假设 源节点为0号节点,则dis[i] 解表示0号节点到 i 号节点的最短距离,还有一个open表和close 表。
其中open表中存放的是已经找到最短路径的节点,close 表中存放的是未找到最短路径的节点。初始时open表中只有源节点。
1、在close 表中找一个节点距离源节点最近的节点 k (即在close的所有节点中 dis[k] 的值最小)将 k 节点加入到open 表中。
2、更新close 表中的所有节点的dis[] 的值,如果通过k节点到达close中的节点的距离比原来的dis[]中的值小,就更新dis[]中的值,否则的话,不跟新。
3、重复1 、 2操作,直到close 表中的节点数为空为止。
上面就是Dijkstra算法的基本思想,Dijkstra算法只能求解没有负权边的图的最短路径,如果一个图的最短路径中存在负权边,则不能用Dijkstr算法求解,对于存在负权边的有向图的求解方法,可以用Bellman-ford 或 SPFA 算法 求解
Greed-Best-First-Search算法
该算法是利用贪婪策略实现的一种算法,每次选择的下一个节点都是在当前节点所能到达的节点中距离终点最近的节点,
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
假设这个是地图,求两点之间的最短距离
最Greed-Best-First-Search 算法中,总是先计算四周的节点到终点的距离,哪个距离终点最近,
就选择哪个节点,当然在没有障碍物的情况下,这种方法没有错误
如果存在障碍物,则不一定能找到最短路径,例如下面的地图 2 表示障碍物 1 表示可以通行
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 2 2 2 2 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
Greed-Best-First-Search 计算到终点位置的最短距离公式这里采用了曼哈顿方法
//(x,y) 表示当前位置 (endx,endy)表示终点位置
res = abs(x - ensx) + abs(y - endy);
启发函数
启发函数是结合上面的两种算法,这里先给出启发函数的形式
F(N) = G(N) + H(N);
这个函数的形式并不复杂,
G(N) 表示采用的Dijkstra 算法计算出的已经经过的路径的长度,
H(N) 表示采用 Greed-Best-First-Search 算法计算出的当前位置距离终点的最短距离
这两个数值的和就是起点到终点的最短距离,所以在选择路径的时候,时刻选择F(N)最小的位置
A*算法的代码实现
直接在代码中注释解释