一、A* 算法简介
A* algorithm is a popular choice for graph search. Breadth First Search is the simplest of the graph search algorithms. Graph search algorithms, including A*, take a “graph” as input.
A* algorithm is a modification of Dijkstra’s Algorithm that is optimized for a single destination.
A* algorithm uses both the actual distance from the start and the estimated distance to the goal.
From: https://www.redblobgames.com/pathfinding/a-star/introduction.html
二、A* 算法的估值更新
A* 算法的估值更新,需要用到 A* 算法的启发函数 h(x)。
相应地,A* 算法的可表示为:f(x)=g(x)+h(x),其中:
f(x):从初始状态经由当前状态 x 到目标状态的估计代价
g(x):从初始状态到当前状态 x 的实际代价
h(x):从当前状态 x 到目标状态的估计代价
注意:
1. 针对 f(x)=g(x)+h(x),如果 h(x)=0,就是普通的BFS算法;如果 g(x)=0,就是贪心算法。所以 A* 算法就是“BFS+贪心”。
2. 启发函数 h(x) 决定了A*算法的优劣。启发函数 h(x) 包括曼哈顿距离、对角线距离(切比雪夫距离)、欧几里得距离等。启发函数 h(x) 必须满足单调性(即估计代价不会超过从当前状态 x 到目标状态的的实际代价)。A*算法的主要难点是设计合适的 h(x) 函数,而编码很容易。
3. 在二维平面上,有3种方法可以近似计算 h(cur)。
下面的 (cur.x, cur.y) 是 cur 点的坐标,(t.x, t.y) 是终点 t 的坐标。
(1)曼哈顿距离
应用场景:只能在四个方向(上,下,左,右)移动。
h(cur)=abs(cur.x–t.x)+abs(cur.y–t.y)
(2)对角线距离
应用场景:可以在八个方向上移动,例如国际象棋的国王的移动。
h(cur)=max(abs(cur.x–t.x), abs(cur.y–t.y))
(3)欧几里得距离。
应用场景:可以向任何方向移动。
h(cur)=sqrt((cur.x–t.x)^2+(cur.y–t.y)^2)
非平面问题,需要设计合适的 h 函数。
4. 计算 h(x) 时,要忽略路径中的障碍物。因为 h(x) 是对剩余距离的估算值,而不是实际值,因此 h(x) 为估计代价。
5. A*算法中,地图必须是可行的,即不存在无法通过的障碍物或无法到达的区域。同时,需将地图“网格化”,“网格化”其实就是将连续的问题离散化。
6. A*算法中,选取下一个格子的标准并不是离终点最近,而是离起点和终点的距离之和最近。
三、A* 算法的步骤
在 A* 算法中,需要使用两个辅助表来记录结点。
一个用于记录可被访问的结点,称为 openList 表;一个是记录已访问过的结点,称为 closeList 表。
A* 算法的终止条件是终点在 closeList 表中(找到路径)或 openList 表为空(找不到路径)。
-------------------------------------
A* 算法的简单步骤如下:
1.把起始节点添加到openList;
2.重复如下步骤:
a) 寻找 openList 当中 F 值最低的结点,将其称为当前结点;
b) 将该结点从 openList 中删除,并加入 closeList 当中;
c) 对于当前结点相邻的 8 个结点
* 如果它不可通过或者已在 closeList 当中,忽略它,反之如下;
* 如果它不在 openList 当中,将其添加进去。把当前结点作为它的父结点。同时更新它的 F,G 和 H 值。
* 如果它已经在 openList 当中,通过判断沿当前结点到它的路径的 G 值是否更小,若更小,则将当前结点作为它的父结点,同时更新它的 F 和 G 值。否则,不做任何操作。
d) 当目标结点已添加到 closeList 时,路径已被找到;或者没有找到目标结点,此时 openList 已为空。这时候,路径不存在。以上两种情况结束循环。
3.路径回归。从目标结点开始,沿着每一个结点的父结点移动至起始结点,形成的路径即为所求路径。