A*算法求解迷宫最短路问题(C++,VScode)

A*算法求解迷宫最短路问题(C++,VScode)


开始正文之前,先介绍一篇对我帮助较大一篇博客: A*算法讲解

一、算法思想及实现思路

1.估价函数:

F = G + H,起点为S,终点为E,从S到E经过节点N,S->N所要耗费的代价为已知代价G,N->E所要耗费的实际代价未知,因为当前在节点N,还未走到终点,所以未知路径,代价也未知,但可以设计启发函数来估计N到E要耗费的代价H,从而得出S->N->E所要耗费的代价的估计值F = G + H。

2.open表,closed表:

起初,将起点放到open表中,对open表初始化,因为可以在地图上斜着走,所以对节点扩展时,设当前正在扩展的节点为N,要沿八个方向按顺序依次访问N的相邻八个节点,设相邻八个节点的某个节点为M,访问N周围节点时会遇到以下三种情况:

(1)节点在之前从未被访问过,即节点既不在open表,也不在closed表,此时节点放到open表中,放入之前,应先计算M的F,G,H值,并把当前正在被扩展的节点N作为它的父节点,M的G值是由父节点的G值加上父节点到M的实际距离(二者相邻),再根据估价函数计算H值,再计算F值,根据F值将M放入到open表的正确位置,open表中排在前面的,估计代价F值就越小。

(2)节点在之前被访问过,但未被扩展,即节点在open表,但不在closed表,此时可能要对M的G,F值更新,H值不变,因为它在地图的位置没变,相对终点位置没变,因为M在之前被访问过,所以它已有父节点,但不是当前正在被扩展的节点N,此时,计算N->M要耗费的代价,再加上N的G值,即为S->N->M所要耗费的实际代价,比较新G值与旧G值,若新<旧,则更新M的节点信息,将N作为它的父节点,不在以之前的父节点继续作为当下的父节点,并将旧G值用新G值覆盖,重新计算F值,然后根据F值调整M在open表中的位置(往前调)。

(3)节点在之前已被扩展过,即节点不在open表,在closed表,此时可以直接忽略M,转到N的下一个相邻节点。

当找到终点,且终点被放到closed表中,即可结束搜索,根据子节点存储的父节点信息,往回走,便能得到最短路。

二、问题求解所用到的方法以及数据结构

1.优先队列

根据open表的特性,优先队列正好能和它相匹配,优先队列里的每一个元素都是一个结构体变量,存储自己的行列,以及F,G,H值,当然,需要对运算符重载,保证入队的元素是根据F值进行排序的。

2.二维结构体数组

(1)作用:用来存储每一个节点的信息:父节点的位置,及自身的F,G,H值;记录最短路径,终点扩展后,根据该数组,便可从终点返回至起点。

(2)使用原因:优先队列每次只能修改或读取队首这一个节点,其他节点无法修改,只能出队才能遍历,很不方便,不能反复地、灵活地对队列中的任意一个节点进行修改或读取,也正是如此,如果队列中地节点信息要更新(说明从其它路径到该节点的G值更小),则直接创建一个新的节点,新旧节点均指向地图上的同一位置,即,某一位置的节点信息已经在队列中后,若要对节点信息修改,由于队列只能取队首,不能取到其他节点,所以,最好的做法便是重新为该位置创建新节点,放到队列中,新节点的F值比旧节点的F值更小,故而拍在队列的前面,排在前面的优先扩展,扩展后的节点所对应的位置,该位置的其他在队列中的节点不在扩展,直接跳过,因为那已经没有利用价值了。

3.估价函数的设计
(1)曼哈顿法:

节点到终点的行之差的绝对值+列之差的绝对值:
∣ r 1 − e n d r ∣ + ∣ c 1 − e n d c ∣ |r1-end_r| + |c1-end_c| r1endr+c1

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

  №

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值