A*
算法特点
- 启发式搜索算法
- 适用于静态环境中的路径规划
- 求解源点到目标点之间的最短路径,需要指明目标点(即目标点位置已知,这样才能有效的计算 h ( x ) h(x) h(x))。
1 基本概念
-
启发式方法:
一种根据经验规则进行发现的方法
-
启发函数 h ( x ) h(x) h(x):
-
曼哈顿距离: 只允许上下左右移动的情况
D = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ D= |x_1-x_2| + |y_1-y_2| D=∣x1−x2∣+∣y1−y2∣ -
欧几里得距离: 允许朝任意方向移动
D = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 D=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2} D=(x1−x2)2+(y1−y2)2 -
其他: 例如对角距离等
-
2 算法实现
评价函数
f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)
- g ( n ) g(n) g(n) 表示从起点 S S S 到的最优路径的实际成本, 即从起点到当前节点已经走过的路程。(其实可以理解为 Dijkstra 算法中的 dis 数组)
- h ( n ) h(n) h(n) 表示从当前节点到目标节点 T T T 的预估成本, 使用启发函数来计算, 根据具体问题, 一般为曼哈顿距离或者欧氏距离
算法输入
要具体研究一个算法,首先定义输入结构:
- 起点 S S S 坐标已知 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),终点 E 坐标已知 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)。
- 输入地图为一个 N ∗ N N*N N∗N 的方阵,其中每个元素代表一个实际地图的像素,假设每一个相邻像素之间的距离为 1 1 1,斜对角相邻元素的距离为 2 \sqrt{2} 2 ,其中有一些像素为障碍物。
这里首先定义两个集合:
- 开放列表(OpenList):已经访问过,但是没有确定最短路径的节点。
- 关闭列表(CloseList):已经确定了源点到其的最短路径的节点。
算法流程
-
将起点 S S S 放入开放列表 (openList) 中.
-
遍历开放列表
-
计算列表中的每一个节点 n n n 的评价函数 f ( n ) f(n) f(n) , 查找 f ( n ) f(n) f(n) 函数值最小的节点, 将这个节点作为当前要处理的节点 N N N
-
对于当前正在处理的节点 N N N , 遍历与之相邻的其他所有节点 N n e a r N_{near} Nnear
-
假设当前正在处理的相邻节点为 N n e a r N_{near} Nnear
-
N n e a r N_{near} Nnear 已经在关闭列表中(已经确定最短路径),或者不可达(障碍物),则忽略该节点
-
N n e a r N_{near} Nnear 不在开放列表中(未被访问过),则将其加入开放列表,将当前节点 N N N 设置为 N n e a r N_{near} Nnear 的父结点,计算节点 N n e a r N_{near} Nnear 的评价函数 f ( N n e a r ) f(N_{near}) f(Nnear) , g ( N n e a r ) g(N_{near}) g(Nnear)
-
N n e a r N_{near} Nnear 已经在开放列表中(已经访问过但未确定最短路径),则需要检查这条路径(节点 N N N 到节点 N n e a r N_{near} Nnear 的路径)是否更好,参考指标为 g ( N n e a r ) g(N_{near}) g(Nnear) ,若 g ( N n e a r ) g(N_{near}) g(Nnear) 更小,则说明该路径更好,则将它的父亲节点(设为节点)设置为当前节点 N N N ,并重新计算 f ( N n e a r ) f(N_{near}) f(Nnear) 。
g ( N n e a r ) = m i n { g ( N ) + d i s t a c e ( N , N n e a r ) , g ( N n e a r ) } g(N_{near}) = min\left\{\ g(N)+distace(N,N_{near})\ ,\ g(N_{near}) \ \right\} g(Nnear)=min{ g(N)+distace(N,Nnear) , g(Nnear) }
-
-
-
当前节点 N N N 处理完毕, 移动到关闭列表,表示该节点已经不需要被继续关注。
-
-
重复步骤「2」直到满足以下条件之一,算法结束:
- 终点进入了开放(找到了起点到终点的路径)
- 开放列表为空,仍未找到终点(无法找到起点到终点的路径)
-
路径回溯:如果在步骤「3」中,存在从终点到起点的路径,则回溯找到最短路径:
从终点开始,每一个节点都沿着父亲节点移动,直到找到起点。