码迷,mamicode.com
首页 > 编程语言 > 详细

A*算法

时间:2015-08-15 18:06:36      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

A*算法

以前做项目时候,经常听到A*算法,感觉很高大上,今天闲来无事,对这个算法了解了下,主要参考

http://zm8.sm-img5.com/?src=http%3A%2F%2Fblog.csdn.net%2Fshanshanpt%2Farticle%2Fdetails%2F8977512&uid=aff73364c6b5346a25df05847b0ba813&hid=33f0813de0404e86840c9d053a4e27d2&pos=5&cid=9&time=1439515838327&from=click&restype=1&pagetype=0040000002000408&bu=web&query=a%E7%AE%97%E6%B3%95%E5%92%8Ca%E6%98%9F%E7%AE%97%E6%B3%95&uc_param_str=dnntnwvepffrgibijbprsvpi

并结合自己的想法,写下这篇随记!

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:结束,根据退出循环的条件可以知道到底有没有找到路径!

A*算法

标签:

原文地址:http://www.cnblogs.com/Hailong-Said/p/4732817.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!