标签:
A*算法
以前做项目时候,经常听到A*算法,感觉很高大上,今天闲来无事,对这个算法了解了下,主要参考
并结合自己的想法,写下这篇随记!
A*算法用到的数据结构
A*算法是很经典的只能启发式搜索算法,其他的搜索算法DFS,BFS之类。
我们要想从绿色的点到红色的点,需要启发式得去找一条路径,到底怎么去找呢,开始没有办法,只能从开始点慢慢尝试!我们需要定义一个OPEN表,里面放的是当前有可能作为路径上的点。其中这些点都要有父节点,方便当我们找到最后一个点的时候,需要通过父节点回溯,找到所有点直到开始节点!一个CLOSE列表,列表中保存所有不需要再次检查的方格,也就是说以及处理过的点。
比如
在图中,暗绿色方格是你起始方格的中心。它被用浅蓝色描边,以表示它被加入到关闭列表中了。所有的相邻格现在都在开启列表中,它们被用浅绿色描边。每个方格都有一个灰色指针反指他们的父方格,也就是开始的方格。
接下来我们应该选择哪一个点继续考虑呢!我想大家应该知道所谓的启发函数,根据这条路径可能的代价,用F表示,F = G + H
G = 从起点A,沿着产生的路径,移动到网格上指定方格的路径耗费。
H = 从网格上那个方格移动到终点B的预估移动耗费。
由于G值是要根据路线来确定路径耗费,一般是利用当前点的父节点的G+父节点到当前点的代价;而在计算H时候,这部分由于到达终点的路线不确定,我们只是按照某个统一的标准来描述到目标物的相对远近的趋势,它只是个猜测,这经常被称为启发式的。这个标准可以是欧式距离或者是“曼哈顿”法(当前的点,到目标点,横向和纵向的格子数相加),A*算法用到的数据结构基本就介绍完了。
A*算法的思想
当在某步时候,我们可以走的点是哪些(存储在OPEN表里),这集合中的每个点假设是在最终的路线上,要是我们知道这条路线所需的代价是多少(由F值衡量),那么我们就可以直接在这个集合中选出最小的F值(用堆排序处理OPEN表里节点,方便找最小F值)来当做我们下步要走的节点(注意,由于这个节点可能不在最终路线上,所以需要CLOSE列表来存储已经走过的点,同时在OPEN表消除该点),这样直到OPEN表中出现终点或者是在CLOSE列表出现。
下面是具体的过程:
对于起始点以及周围点的G值,H值和F值,下图可以很清晰的看到!( 左上角是F,左下角是G,右下角是H ) 这里移动一步代价为10,对角14
接着计算:
然后从OPEN表中,我们使用堆排序处理这个表中的节点,可以较快的选择一个F值最小的,然后考虑其周围邻居,再循环处理!直到终点加入CLOSE中,寻路结束!或者OPEN空了,没找到路径!
可以看到,F最小的是起始点右边的那个点,下面框框表示的~
然后再考虑其邻居:
此时对于其邻居有几种可能性!
1:邻居已经在CLOSE表中了,那么不需要考虑了~
2:邻居是障碍物,不需要考虑了e
3:邻居不在OPEN表中,那么将邻居加入OPEN,并将次邻居的父节点赋值为当前节点
4:邻居在OPEN中,那么需要看看此邻居点的G值与当前点的(G值+当前点到邻居点的距离(10或者14))的大小,如果从此点走更近(即G值更小),那么将此点的父节点换成当前点!
那么我们按照上面的思路,知道终点加入CLOSE表!( 终极图示如下 )
最终我们可以得到路径:( 之前我们说过,由父节点往前回溯就很easy的得到路径了~ )
说了这么多,也不知道说的行不行,还是需要总结一下!
算法描述
1:将起始点加入OPEN表中
2:循环直到OPEN为空或者终点加入CLOSE表中
否则:找到OPEN表中F值最小的节点(使用堆排序得到小值点),将此点从OPEN删除,加入CLOSE!
(此时最小点已经取出,那么需要从新排序OPEN表,是的第一个点是最小F的点!)
对8个邻居进行处理:
若:1:邻居已经在CLOSE表中了,那么不需要考虑了~
2:邻居是障碍物,不需要考虑了e
3:邻居不在OPEN表中,那么将邻居加入OPEN,并将次邻居的父节点赋值为当前节点
4:邻居在OPEN中,那么需要看看此邻居点的G值与当前点的(G值+当前点到邻居点的距
离 (10或者14))的大小,如果从此点走更近(即G值更小),那么将此点的父节点换成当前 点! (注意:对于同一个点,G值下,那么F必须小!因为H是相同的!)
注意:当父节点改变后,OPEN表中的最小点可能会变化,那么需要再次排序得到最
小点!
3:结束,根据退出循环的条件可以知道到底有没有找到路径!
标签:
原文地址:http://www.cnblogs.com/Hailong-Said/p/4732817.html