核心在于估值函数设计:
f(n)=g(n)+h(n)
f(n)是每个可能试探的点的估值,由两部分组成:
g(n)表示从起始搜索点到当前点的代价(通常用某节点在搜索树中的深度来表示);
h(n)表示当前节点到目的节点的估值,h(n)设计的好坏,直接影响算法能否称为A*算法。
成为A*算法的充分条件:
1、搜索树上存在着从起始点到终了点的最优路径。
2、问题域是有限的。
3、所有节点的子节点的搜索代价值>0。
4、h(n)=<h*(n) (h*(n)为实际问题的代价)。
2、算法的实现
求此起始点V0->途径任意顶点->目标顶点V5的最短路径。
A*算法的核心过程,就在每次选择下一个当前搜索点时,从所有已探知但为搜索过点中(可能是不同层,也可能不在同一条支路上),选取f值最小的节点进行展开。
所有“已探知但未搜索点”通过一个按f值升序的队列(优先队列)进行排列。
这样,按照广度优先的算法,从优先队列中弹出队首元素(f值),对其可能子节点计算g,h和f值,知道队列为空(无解)或找到终止点。
3、A*算法流程
首先将起始节点S放入OPEN表,CLOSE表为空:
1、如果OPEN表不为空,从表头取一个节点n,如果为空算法失败;
2、n是目标解吗?是,找到一个解(继续寻找,或终止算法);
3、将n的所有后继节点展开,就是从n可以直接关联的节点(子节点),如果不在CLOSE表中,就将它们放入OPEN表,并把S放入CLOSE表,同时计算每一个后继节点的估价值f(n),将OPEN表按照f(x)排序,最小的放在表头,重复算法,回到1。
closedset :=the empty set //已经被估算的节点集合
openset :=set containing the initial node //将要被估算的节点集合
g_score[start] :=0 //g(n)
h_score[start] :=0 //h(n)
f_score[start] :=0 //f(n)
while openset is not empty //若OPEN 表不为空
x := the node in openset having the lowest f_score[] value//x为OPEN表中最小的
if x = goal//如果x是一个解
return reconstruct_path(came_from, goal)
remove x from openset
add x to closedset
CLOSE表
for each y in neighbor_nodes(x)//对于x邻居集中的每个邻居节点y
if y in closedset//如果y在CLOSE表中
continue//那么不进行处理
tentative_g_score := g_score[x] + dist_between(x, y)//y到目的的g(n)估算等于g(x)加上xy之间的代价
if y not in openset//如果y不在OPEN表中
add y to openset//将y加入OPEN表
tentative_is_better := true //是否是更佳路径,是
else if tentative_g_score < g_score[y]//如果估算探索g(n)小于g(y)
tentative_is_better := true//是否更佳路径,是
else
tentative_is_better := false//否则非更佳路径
if tentative_is_better = true//如果是更佳路径
came_form[y] := x//将y设置为x的下一目标节点
g_score[y] := tentative_g_score//g(y)等于估算的探索g(y)
h_score[y] := heuristic_estimate_of_distance(y, goal)//x-->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 the empty path//直到路径为空停止
算法性能:外循环中每次从OPEN表中取一个元素,共取了n此(共n个节点),每次展开一个节点的后续节点时,需要O(n)次,同时再对OPEN做排序,OPEN表大小事O(n)级别的,快排序就是O(nlogn),复杂度是O(n^2*logn)。
A*最短路径算法
目标:从当前位置A到目标位置B找到一条最短的行走路径。
方法:
从A点开始,遍历所有的可走路径,记录到一个结构中,记录内容为(位置点,最小步数)。
当任何第二次走到一个点的时候,判断下最小步数是否小于记录的内容,如果是,则更新掉原最小步数,一直到所有的路径点都不能继续了位置,最终那个点被标注的最小步数既是最短路径。
而反向找跟他相连的步数相继少一个值得点连起来就形成了最短路径,当多个点相同,则任意取一条即可。
总结:
A*算法实际是个穷举算法。