我最初的学习文章来自这里的转载。
A*算法详细阐述
最后我来打个总结。
先下几个定义
F = G+ H
G的值是该结点的距离到达父结点的距离,加上父结点到爷爷结点的距离,直到递归父结点为 起始点。
这里距离,还可以说成 消耗,花费之类的。
上面链接里的G,就是由距离求出来的,斜着的距离是14,其他为10.
H的值是该点到终点的一个预估距离,预估消耗,是个定值。(也就是说此时的地图数据是静态的)
待处理点:deal node
open 和 close :2个装node 的集合
学习A*算法,我们要关注这几个问题:
- 什么点 进入 open?
起点进入open
处理点周围可以处理的(墙啊,河流之类的,不可处理),非close、非open的进入open - 什么点 进入 close?
待处理的点进入close - 什么点为 待处理的点
遍历open,找出F最小的点 - 什么点为该点的父结点
当一个非open的点加入open时,待处理点为该点的父结点。
以及当处理点周围有 新G 比 原G更小的点时, 处理点变为该点的父结点。 - 一个点什么时候G值会变化?
当这个点处于open中,且在一个deal node 周围,并且这个点的父结点改为 deal node 后,新G比原G小,则父结点变化带动了G的变化。
流程:
初始设置: open中加入起点,起点的F = 0
- 判断open里有 终点吗? 有 就结束,没有就继续。 判断open为空吗?为空则结束。
- 找出open中F最小的点作为 deal Node, deal Node放入 close中
- 把deal node 周围 的 close点、 false点 不管
- 把deal node 周围的 open点 的父结点 设置为 deal node点,求出新的G 与原G比较,
如果比原G小,则ok, 否则 该点的父结点重新设置为原父结点 - 把deal node 周围的其他的点 放入 open中,设置其父结点为 deal node ,并求出F、G、H。
- 回到1中。
贪心的思想如何体现的?
什么是贪心?即当前做出的操作是目前看来最好的。
A*每次从open中选出 F 最小的点作为 deal node,因为F收到了H影响,所以势必deal node有着向 终点靠近的趋势。
每一次选出 deal node后,更新了 deal node 周围的、还在open中的node的G,保证了这些点,都是距离起点消耗最低的点(消耗即距离)。
所以当 结束条件, 终点进入open时,open会成为某个点的子结点。而它的父结点是被上一句话保证过的,所以终点也是当前到达起点最短的点。
每一步都保证是当前最短,最终就一定是最短吗?
不会
例如:
1 - 10 - 10 - 10 =31
10 - 1 - 1 - 1 = 13
第一次选择最短的 1, 后面的每一次选择都是当时最短的,但上面那种最终长于第二种。
因为我这一步的选择可能会坑一些,但这次亏了之后的选择就会大赚。