原文链接:http://blog.youkuaiyun.com/luckyxiaoqiang/article/details/6996963
A*搜寻算法,俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中的NPC(Non-Player-ControlledCharacter)的移动计算,或线上游戏的BOT(ROBOT)的移动计算上。该算法像Dijkstra算法一样,可以找到一条最短路径;也像BFS一样,进行启发式的搜索。
A*算法是一种启发式搜索算法,启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无谓的搜索路径,提高了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。
A*算法的公式为:f(n)=g(n)+h(n),g(n)表示从起点到任意顶点n的实际距离,h(n)表示任意顶点n到目标顶点的估算距离。 这个公式遵循以下特性:
- 如果h(n)为0,只需求出g(n),即求出起点到任意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法
- 如果h(n)<=“n到目标的实际距离”,则一定可以求出最优解。而且h(n)越小,需要计算的节点越多,算法效率越低。
对于函数h(n),估算距离常用的方法有:
- 曼哈顿距离:定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里德空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:|x1 - x2| + |y1 - y2|。
- 欧氏距离:是一个通常采用的距离定义,它是在m维空间中两个点之间的真实距离。在二维和三维空间中的欧氏距离的就是两点之间的距离。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的欧氏距离为: sqrt((x1-x2)^2+(y1-y2)^2 )。
- 切比雪夫距离:是两个向量之间各分量差值的最大值。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的切比雪夫距离为:max(|x1 - x2| , |y1 - y2|)。
A*算法实现伪代码:
- function A*(start,goal)
- closedset := the empty set
- openset := {start}
- came_from := the empty map
- g_score[start] := 0
- h_score[start] := heuristic_cost_estimate(start, goal)
- f_score[start] := g_score[start] + h_score[start]
- while openset is not empty
- x := the node in openset having the lowest f_score[] value
- if x = goal
- return reconstruct_path(came_from, came_from[goal])
- remove x from openset
- add x to closedset
- foreach y in neighbor_nodes(x)
- if y in closedset
- continue
- tentative_g_score := g_score[x] + dist_between(x,y)
- if y not in openset
- add y to openset
- tentative_is_better := true
- else if tentative_g_score < g_score[y]
- tentative_is_better := true
- else
- tentative_is_better := false
- if tentative_is_better = true
- came_from[y] := x
- g_score[y] :=tentative_g_score
- h_score[y] :=heuristic_cost_estimate(y, goal)
- f_score[y] := g_score[y] +h_score[y]
- return failure
- function reconstruct_path(came_from,current_node)
- if came_from[current_node] is set
- p := reconstruct_path(came_from, came_from[current_node])
- return (p + current_node)
- else
- return current_node
下面给出一个A*(曼哈顿距离)的例子:
■代表起点,■代表终点,■代表障碍,■代表属于OPENSET,■代表属于CLOSEDSET, —— 黄色线段代表最终得出的路径。
方格内左上角代表f(n)即启发函数值,左下角代表g(n),即起点到该点的距离,右下角代表h(n),即该点到终点距离的估值,使用曼哈顿距离,方格上下左右相邻距离为10,对角线相邻为14,曼哈顿距离以10为单位。
(gif动画文件)
A*与Dijkstra,DFS,BFS:
- A*算法,每次从OPENSET中选择 f(n) 最小的节点将其加入CLOESEDSET中,同时扩展相邻节点,可把OPENSET看成一个优先队列,key值为 f(n),优先级最高的先出。
- Dijkstra算法,每次从OPENSET中选择 g(n) 最小的节点将其加入CLOSEDSET中,同时扩展相邻节点,可把OPENSET看成一个优先队列,key值为 g(n),优先级最高的先出。
- DFS算法,每次从OPENSET中选择最晚被加入的节点将其加入CLOSEDSET中,同时扩展相邻节点,可把OPENSET看成一个栈,后进先出。
- BFS算法,每次从OPENGSET中选择最早被加入的节点将其加入CLOSEDSET中,同时扩展相邻节点,可把OPENSET看成一个队列,先进先出。
下面通过几个例子对比一下5种算法,A*(曼哈顿距离),A*(欧氏距离),A*(切比雪夫距离),Dijkstra,Bi-Directional Breadth-First-Search ,以显示A*算法的优越性。
例一:
1.1 A*(曼哈顿距离)
1.2 A*(欧氏距离)
1.3 A*(切比雪夫距离)
1.4 Dijkstra
1.5 Bi-Directional Breadth-First-Search
例二:
2.1 A*(曼哈顿距离)
2.2 A*(欧氏距离)
2.3 A*(切比雪夫距离)
2.4 Dijkstra
2.5 Bi-Directional Breadth-First-Search
例三:
3.1 A*(曼哈顿距离)
3.2 A*(欧氏距离)
3.3 A*(切比雪夫距离)
3.4 Dijkstra
3.5 Bi-Directional Breadth-First-Search
例四:
4.1 A*(曼哈顿距离)
4.2 A*(欧氏距离)
4.3 A*(切比雪夫距离)
4.4 Dijkstra
4.5 Bi-Directional Breadth-First-Search
附:
我从网上找到的比较好的一个算法演示程序,下载地址
http://download.youkuaiyun.com/detail/walkinginthewind/3822153