A*算法 整理

A*算法

注:本文引自https://www.cnblogs.com/chxer/p/4542068.html

0.概念及何时用

概念

​ A*探路搜索,是指在有障碍物的时候,寻找到达目的地最短路径的搜索。

先介绍一些前置知识助于自己理解A*:

  1. 启发式搜索:这是对每一个搜索位置进行评估,得到好的位置,再从这个位置进行搜索直到目标。

这样子好处是:剪枝,效率更高。

启发式搜索的关键是如何进行估价。

  1. 估价函数:从当前节点到目的的预估费用。此估计就是启发式的。在寻路问题与迷宫问题中,通常用manhattan估价函数预估费用。
  2. A*与一般搜索的关系区别:dfs bfs是A*算法的特例。

对于BFS算法,是从当前节点扩展出的每个节点(未被访问)放进队列,从而进一步拓展。其估价函数h为0,边权为1,无任何启发式信息。DFS的h为0。

  1. 选取最小估价:选择最小估价的节点,用到最小优先级队列(最小二叉堆),C++ STL中有现有的数据结构priority_queue,需要重载自定义节点操作比较符。
  2. A*算法评价:理论上时间最优,但空间增长为指数级别。
  3. IDA*算法:迭代加深A*算法,解决空间指数增长问题,甚至可以不用优先级队列。

1.步骤

1.jpg

绿色为起点,红色为重点,蓝色为障碍物。

我们应注意到,整个区域被划分为正方形网格,而我们的搜索区域是正方形扩散。

那么这是算法第一步:

简化搜索区域

我们将每一个正方形区域用二维数组来储存,二位数组的每个元素代表其位置,二维数组的值可以表示为可以通过以及不可通过。

那么路径的求解就是从绿色方块A到红色方块B的二维数组方块的集合。

我们把路径经过的区域叫节点,不叫方块。因为路径完全可以分割成不是正方形的形状,如六边形,矩形。只不过正方形是最简单的情况。

开始搜索

从A 开始,检查相邻的方格,向外拓展。

具体操作:

  1. 从A开始,将其放入open_list中,open_list 像一个购物清单。其中的内容可能是最终的路径也可能不是。基本上这是待检查方格的清单。

  2. 寻找周围可到达方格,也将其加入open_list中,并保存为点A的父方格。父方格的作用很重要,后续会讲到。

  3. 开启列表删除点A ,加入close_list,这是保存不需要检查的方格

    2.jpg

蓝框描边的是在close_list中,旁边扩散的箭头是其父节点。

接下来就是要开始启发式搜索用哪个节点了,这里的关键是路径评分。

路径评分

具体评分的函数写法F=G+H

*G:从起点开始,移动到现节点的移动耗费。比如这里每移动,横竖向10,对角向14(不用根号是为了简化)

*H:现节点移动到终点的预估耗费。这里就被称为启发式,因为他只是一个猜测。预估的办法这里提供一种manhattan估价函数预估费用。即计算从此节点到终点,只走横向竖向的数量总和,再乘以10.(忽略障碍物),请注意这里是估算,非实际值。所以他叫启发式。

那么最后的评分就是两者和。

3.jpg

这是评分结果。

继续搜索

我们从open_list中选择F最低的方格,对其做如下处理:

1.从open_list移除,加入close_list中去。

2.检查所有相邻格子。跳过open_list中的格子以及不可达的格子(墙,地形),将未被跳过的加入到open_list中,然后他们作为此节点的父节点。

3.如果相邻节点中已有在open_list中的,检查通过新路径快,还是从那个已在open_list中的节点的父节点过来快。

4.jpg

如图,既然我们都在open_list中,那我们检查G值,发现新路径是右+下,G的值为20,原路径是只要对角线,G的值为14,所以明显旧路径好。

5.jpg

重复这个过程直至到达终点。

6.jpg

最后确定路线是从终点沿着父节点倒过来就是路径了。

2.总结

1,把起始格添加到开启列表。

2,重复如下的工作:

a) 寻找开启列表中F值最低的格子。我们称它为当前格。

b) 把它切换到关闭列表。

c) 对相邻的格中的每一个?

​ * 如果它不可通过或者已经在关闭列表中,略过它。反之如下。

​ * 如果它不在开启列表中,把它添加进去。把当前格作为这一格的父节点。记录这一格的F,G,和H值。

​ * 如果它已经在开启列表中,用G值为参考检查新的路径是否更好。更低的G值意味着更好的路径。如果是这样,就把这一格的父节点改成当前格,并且重新计算这一格的G和F值。如果你保持你的开启列表按F值排序,改变之后你可能需要重新对开启列表排序。

d) 停止,当你

​ * 把目标格添加进了关闭列表(注解),这时候路径被找到,或者

​ * 没有找到目标格,开启列表已经空了。这时候,路径不存在。

3.保存路径。从目标格开始,沿着每一格的父节点移动直到回到起始格。这就是你的路径。

posted @ 2022-02-22 23:27  yuezi2048  阅读(21)  评论(0编辑  收藏  举报