A*寻路算法浅析

2023-11-05

  最近刚接触A*寻路算法,听说是一种比较高效的自动寻路的算法,当然,事实也正是如此,这么好的东西,自然是要收入囊中的,说不定什么时候也能派上用场呢。为了学习这个,也是上网找了好多资料,看了好多博客,但是貌似有些关键点没有具体说明,所以自己也是费了不小的劲才完全理解。为了更好的讲解,特意花了一个晚上作了一系列说明图(作图真心不容易啊,如果发现图片有标注错的地方,大家多多包涵呀),希望大家能够有所收获。

启发式搜索

  A*寻路算法是一种用来高效的寻路算法,那究竟是如何寻找最佳路径的呢?请看图:
                  这里写图片描述
  如图所示,图上有A、B两点,中间被墙隔开,我们如何找到一条最短的路径(或者最接近现实的路径),从A走到B呢?
  图上除了A、B两点以及黑黑的墙以外,什么都没有,且别说计算最佳路径了,就连A、B两点的位置我们都无法准确表达出来,我们总该想想,通过什么方式来表达我们的路径,然后才能讨论最短路径的问题。所以我们必须借助工具才行,这工具就是“方格”。也就是说我们可以把这个小地图分割成一个个的小方格,这样便于我们表示A和B的位置,便于表示路径(当然,你可以分其他形状,It’s up to you!只要能达到目标即可),如下图所示:
            这里写图片描述
  现在我们已经很清楚A、B的相对位置了,那接下来我们该怎么办呢?貌似直接找到一条最短的路径比较困难,我们是不是可以这样:我们从A点出发,先找A点邻近的方格,然后判断这个方格是否是最好的位置(离A点比较近,同时离B点也比较近),然后再从这个所谓的“最好的位置”扩展其邻近的方格,再找到一个“最好的位置”,一步一步逼近目标……显然,这是可行的,而我们也正是采用了这种方法。这也就是所谓的启发式搜索(启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无谓的搜索路径,提高了效率)。

路径评分

  现在的问题是,如何判断这是不是“最好的位置”呢?这里涉及到一个估价函数的概念,顾名思义,就是一个评估费用的函数嘛,假如每走一个格子都要花费一定的钱,那你是不是要好好估算一下怎么样花钱最少,走哪条路到B点最省钱(我相信,为了省钱,你一定不会算错吧)。而在寻路问题中,我们通常使用”F=G+H“这样的估价函数对路径进行评估。
  G:代表当前节点到起始点的距离(此处为到A点的距离)。
  H:代表当前节点到终点的距离(此处为到B点的距离)。
  F:则是两者之和。
  也就是说,判断一个位置是否是“最好的位置”,就是判断其F值是否最小。这么说可能有些抽象,不太好理解,那我们来看具体的例子。

算法描述

  首先,我们将起始点(A点)添加进一个叫“开启列表”的集合中(“开启列表”中的节点(方格)都在等待检查是否是“最好的位置”),然后我们检查开启列表中找到F值最低的节点,将其从“开启列表”中移除,再将其添加进一个叫“关闭列表”的集合中(“关闭列表”中存放着所有我们之前检查过的“最好的位置”,所以不需要再次检查),此时只有A点一个节点,所以我们将A点添加进关闭列表,并将A点置为“当前节点”,用来标识这是我们当前搜索到的最好的位置。我们需要通过当前节点来搜索当前节点邻近的节点(八个方向上的节点:上、下、左、右、左上、右上、左下、右下),因为这些点都有可能是A点下一步所走的节点,将它们添加进开启列表中,如图所示:
            这里写图片描述
  大家可以看到,A点被标识成蓝色,邻近的节点被标识为棕色,且上面都包含数字和箭头。
  左下角的数字代表G值:与A节点水平或者垂直的节点到A的距离为10个单位长度(如图C节点),在A节点的斜对角线上的节点到A的距离为14个单位长度(如图D节点)。
  右下角的数字代表H值: H值的计算方法可参考图中的橙色线,图中D点到目标点的距离为:(两个对角线长度)+(一个水平长度)=2x14+10=38。
  左上角的数字代表F值:F= G+H
  箭头: 箭头的指向为该节点的父节点,可看到此时箭头均指向A,因为这些节点是由当前节点A扩展出来的,所以A为这些节点的父节点。
  棕色的节点:表示这些节点在开启列表中。
  蓝色的节点:表示这些节点在关闭列表中。
  接下来我们又要搜索“开启列表”中F值最小的,可以看出图中F值最小的是44,但是有两个44,随便选择一个即可,暂且选择右下角的那一个44吧,好,我们看图说话:
            这里写图片描述
  首先,将我们选中的节点添加进“关闭列表”(图中E点),将E标识为“当前节点”,然后添加其邻近的节点(如图:三个新增的节点),添加新节点时,要忽略障碍物(图中黑色部分),因为障碍物是不可以走的,首先计算三个新增节点G值,此时G值应该这样计算(以E点正下方的节点为例),E点正下方的节点为到E点的距离为10,E点到A点的距离为14,所以E点正下方的节点G值为24,并且箭头指向其父节点E注意(重点): E点邻近的节点还有两个节点(A点已在关闭列表中,忽略检查),但是F、G是之前存在“开启列表”中的,所以我们还要检查这两个点是否需要更新?我们知道,所有E点邻近的点,都有可能成为下一步要走的节点,若此时从E点走向G点,那么路径变为:A→E→G,那么G点的G值为:A到E的距离+E到G的距离= 14+10 = 24,而G点的F值变为:24+40=64。如果将G点更新,那么G点新的F值64比之前的F值50还要大,所以,G点不应该更新,因为我们是为了找更短的路径,F值变大,意味着路径变长,显然是不可取的,所以在这里,我们保持G点状态,同理,F点也是如此。至此,我们得出结论:
  1、一个节点的G值不是一成不变的,与路径的变化有关,但是一个节点的H值是一定的,因为一个节点到目标点的距离总是不变的;
  2、一个节点是否需要更新,看其F值在其路径发生变化后是增大还是减小,如果因为新路径导致节点F值变大,则不更新,如果F值变小,则更新为小的F值。
  现在我们找到了一个“最好位置”,并且添加了新的节点,检查了节点更新情况,那么现在我们又要来搜索下一个了,判断“开启列表”中所有节点,发现还有一个F值为44的节点,毋庸置疑,它是列表中F值最小的节点,依然选择它作为“当前节点”,其周围没有空节点,所以不需要添加新节点,但是有三个邻近的节点在“开启列表”中,上图:
            这里写图片描述
  显然,无论从F→D,还是从F→G,或者是从F→C,都会使这三个节点的F值变大,所以我们不更新此三个节点,让它们保持原有状态。
  熟能生巧嘛,我们最后再按上面的步骤跟着搜索一次:搜索F值最小的节点作为当前节点,此时G节点的F值为50,是最小的,我们将其从“开启列表”中移除,添加进“关闭列表”,标识为“当前节点”,照例,附上一张图:
            这里写图片描述
  图中,G点已被置为当前节点,也新增了一个节点,其邻近的节点中有4个是之前已经在“开启列表”中的节点,我们检查是否需要更新,请仔细观察图中的H节点,上张图的H节点的F值为72,箭头指向E节点,也就是其父节点为E,到H点的路径为:A→E→H,而此时,H节点的F值更新为64,父节点也发生了变化,箭头指向G点,这是为什么呢?因为H点是G点的邻近点,此时由A→G→H的路径,显然比之前A→E→H更短,所以我们更新H点的信息,其父节点也改为G点,因为H点的状态是因为G改变的。
  好啦,不多说了,相信大家经过几次的重复的步骤,应该清楚了整个寻路的流程,现在附上完整的寻路图:
            这里写图片描述 
  很壮观有木有?现在问题来了,这么多节点连在一起,到底哪条路径才是我们要找的路径呢?Don’t worry!大家看到箭头了没有,现在箭头的作用就发挥出来的,每个箭头只有一个方向,都标识着父节点,相当于标记着“来时的路”,现在我们要走回去了,所以我们就从目标点(B点)开始找回去的路,找B点的父节点,再找其父节点的父节点。。。一直岩着箭头(→)找到A点,那一条就是我们要找的最短的路径。如图红色线所示:
            这里写图片描述

总结

  A*算法具体步骤如下:

1、首先将起始点添加进“开启列表”。

2、重复如下步骤:
    
    a) 寻找开启列表中F值最低的节点。我们称其为“当前节点”。

    b) 把它从“开启列表”中移除,并添加进“关闭列表”。

    c) 检查“当前节点”是否是“目标节点”

       * 如果是,停止搜索,跳到第 3 步;

       * 如果不是,继续下面步骤……  

    d) 寻找“当前节点”邻近的节点

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

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

       * 如果它已经在开启列表中,检查新路径对它G值的产生的影响
           
           a. 如果它的G值因为新路径变大,那么保持原来的状态,不作任何改变;

           b. 如果G值变小,说明新路径更好,将其父结点改为“当前结点”,更新G和F值。

    e) 检查列表是否为空,如果为空,说明路径未找到,直接返回,不继续任何步骤。

3、保存路径。从目标节点开始,沿着每一节点的父节点移动直到回到起始节点。这就是我们要找的路径。

  A*寻路算法采用启发式搜索方法,避免了很多无谓的搜索,提高了效率,但是如果我们想搜索的更精确,可以将方格分割得更小,但是方格越多,搜索越慢,在时间上是成指数级增长的,这也是A*算法的一大缺点,但是依然有优化的办法,使用二叉堆,关于二叉堆优化A*算法的方法,我们有机会再探讨。
  
  注:如非特别说明,本博客的博文均为原创,如需转载请注明出处,本文链接:http://blog.csdn.net/yiyikela/article/details/46134339,尊重他人的劳动成果,谢谢!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

A*寻路算法浅析 的相关文章

  • 编程 Pearls - 随机选择算法

    Programming Pearls 第一版第 120 页介绍了从 N 个整数总体中选择 M 个等概率随机元素的算法 InitToEmpty Size 0 While Size lt M do T RandInt 1 N if not Me
  • 使用主方法求解 T(n) = 2T(n/2) + n/log n 和 T(n) = 4T(n/2) + n/log n 之间的差异

    我最近偶然发现了一个资源 其中 2T n 2 n log ntypeMM 宣布复发无法解决 我接受它作为一个引理 直到今天 另一种资源被证明是矛盾的 在某种意义上 根据资源 下面的链接 其中的 Q7 和 Q18 是建议 分别在问题中的1和2
  • 通过分布式数据库聚合作业优化网络带宽

    我有一个分布式 联合数据库 结构如下 数据库分布在三个地理位置 节点 每个节点集群有多个数据库 关系数据库是 PostgreSQL MySQL Oracle 和 MS SQL Server 的混合体 非关系数据库是 MongoDB 或 Ca
  • 确定解决迷宫问题的最小线段数

    我有一个问题 我需要定义一个具有最少数量的顶点的多边形 该多边形与不透明的图像中的每个像素相交或包含每个像素 令 N 为图像中的像素数 我唯一的假设是图像的边界 孔 内不能包含透明像素 并且至少有两个像素是不透明的 举个例子 假设我有以下图
  • 检索受“rowspan”影响的行的列索引的最有效方法是什么?

    考虑下表 table thead tr th th th A th th B th th C th tr thead tbody tr th 1 th td Apples td td Oranges td td Pears td tr tb
  • 寻找距离原点最近的 100 颗恒星的算法

    首先让我提出正确的问题 问 有一个文件包含超过一百万个点 x y 每个点代表一颗星星 a b 处有一颗行星地球 现在 任务是构建一种算法 返回距离地球最近的 100 颗恒星 您的算法的时间和空间复杂度是多少 这个问题在各种采访中被问过很多次
  • 点集子集的最小周长凸包

    给定平面上的 n 个点 没有 3 个共线 给定数字 k 找到 k 个点的子集 使得 k 个点的凸包在 k 个点的子集的任何凸包中具有最小周长 我可以想到一个简单的方法 运行时间为 O n k k log k 找到大小为 k 的每个子集的凸包
  • 将字符串中的“奇怪”字符转换为罗马字符

    我需要能够将用户输入仅转换为 a z 罗马字符 不区分大小写 所以 我感兴趣的角色只有26个 然而 用户可以输入他们想要的任何 形式 的字符 西班牙语 n 法语 e 和德语 u 都可以包含用户输入中的重音符号 这些重音符号会被程序删除 我已
  • 数组中连续元素的最大乘积

    我在现场面试的时候被问到了这个算法问题 由于没有要求我签署保密协议 我将其发布在这里寻求答案 给定一个数组REAL不包含 0 的数字 找到产生最大乘积的连续元素 该算法应在线性时间内运行 我考虑过以下方法 使用两个数组 第一个是利用DP思想
  • URL路径相似度/字符串相似度算法

    我的问题是我需要比较 URL 路径并推断它们是否相似 下面我提供了要处理的示例数据 GROUP 1 robots txt GROUP 2 bot html GROUP 3 phpMyAdmin 2 5 6 rc1 scripts setup
  • 用 C++ 生成 AST

    我正在用 C 制作一个解释器 到目前为止我已经有了词法分析器来生成标记 问题是我不确定如何生成 行走 解析树 我正在考虑使用数组数组来制作解析树 但我不确定如何以正确的顺序将标记实际插入到解析树中 我不确定是自上而下 左右还是自下而上 左右
  • 数学组合的完美最小哈希

    首先定义两个整数N and K where N gt K 两者都在编译时已知 例如 N 8 and K 3 接下来 定义一组整数 0 N or 1 N 如果这使答案更简单 并调用它S 例如 0 1 2 3 4 5 6 7 的子集数量S wi
  • 计算两点之间的最短路线

    过去几周我一直在开发一款多人 HTML5 游戏 使用nodejs and websockets 我已经被这个问题困扰了一段时间 想象一下 我用数组实现了这个平铺地图 如下所示 1 or 棕色瓷砖 路上有障碍物 玩家无法通过 0 or 绿色瓷
  • 找到一条穿过任意节点序列的最短路径?

    In 这个先前的问题 https stackoverflow com questions 7314333 find shortest path from vertex u to v passing through a vertex wOP询
  • 归并排序中递归树的高度log(n)+1是怎么来的

    我按照 stackoveflow 的建议阅读了一些问题和答案 我正在遵循 cormen 的 算法简介 一书进行自学 那本书里已经解释得很清楚了 但唯一没有解释的是如何在合并排序分析中计算树的高度 如果在后面的章节中对此进行解释的话 我仍然在
  • 在 O(n) 时间内排序?

    我被这个问题困扰了 2周 知道如何处理它吗 令 L 为 n 个不同整数的列表 假设 L 的 x 的元素在 1 750 范围内 设计线性排序算法对 L 的元素进行排序 我已经尝试过插入排序 但我不确定我的方法是否正确 Construct an
  • 实施二分查找有哪些陷阱? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 二分查找比看起来更难实现 虽然二分搜索的基本思想相对简单 但细节可能出人意料地棘手 Donald Knuth 新的二分搜索实现中最有可
  • 举例解释bpe(字节对编码)?

    有人可以帮忙解释一下背后的基本概念吗BPE模型 除了这张纸 https arxiv org abs 1508 07909 目前还没有那么多解释 到目前为止我所知道的是 它通过将罕见和未知的单词编码为子词单元序列来实现开放词汇表上的 NMT
  • 在java中使用BUBBLE SORT对二维字符串数组进行排序

    类似的问题已经被问过 但从来没有关于二维字符串数组 因此在尝试了很长时间之后我找不到我想要的 我正在尝试使用 BubbleSort 对 java 中的 2D 字符串数组进行排序 作为输入 我收到一个二维字符串数组 一个表 以及您应该排序的
  • 动态规划 (DP) 中的重叠子问题是什么?

    为了使动态规划适用 问题必须具有两个关键属性 最优子结构 and 重叠子问题 1 https en wikipedia org wiki Dynamic programming 对于这个问题 我们只关注后一个属性 有各种不同的定义重叠子问题

随机推荐

  • mpeg gpcc编译

    gpcc 编译 1 编译 mkdir build cd build cmake make 2 生成配置文件 cd cfg 进入配置文件 bash scripts gen cdg sh 执行转换设置格式脚本 遇到 坑1 坑1 若能正常执行脚本
  • pip使用总结(持续更新)

    持续总结python pip遇到过的坑 1 pip镜像源 阿里镜像 临时 pip install xxx i http mirrors aliyun com pypi simple trusted host mirrors aliyun c
  • ms-repeat 循环

    ms repeat 可以写成 ms repeat el 后面的el 相当于给每个节点定义的变量名 还可以定义成ms repeat m避免与上级循环的变量重名 ul class times li a href el year a li ul
  • perp系列之七:perp手册

    perp系列之七 perp手册 版本说明 版本 作者 日期 备注 0 1 ZY 2019 5 29 初稿 目录 文章目录 perp系列之七 perp手册 版本说明 目录 1 该发行版包括以下手册页 perp intro 8 perp set
  • 服务器端安装jupyter notebook并在本地使用与环境配置一条龙服务【服务器上跑ipynb】

    linux服务器端安装jupyter notebook并在本地使用 1 生成配置文件 2 配置Jupyter notebook密码 3 修改配置文件 jupyter jupyter notebook config py 4 本地访问远端的服
  • 微调Hugging Face中图像分类模型

    前言 本文主要针对Hugging Face平台中的图像分类模型 在自己数据集上进行微调 预训练模型为Google的vit base patch16 224模型 模型简介页面 代码运行于kaggle平台上 使用平台免费GPU 型号P100 笔
  • About the Storage allocation

    It doesn t matter what programming language u use it s all about the usage of variable storage management 1 Static Dynam
  • 刷爆力扣!反超对象第五天之最长公共前缀

    目录 1 题目解析 2 代码提交 3 知识点学习 1 题目解析 题目 编写一个函数来查找字符串数组中的最长公共前缀 如果不存在公共前缀 返回空字符串 示例 1 输入 strs flower flow flight 输出 fl 此题其实也很简
  • ant design pro中umi-request拦截请求统一处理报错提示

    ant design pro项目请求用的是umi request 对于请求不成功的情况需要给用户错误提示 但是每个请求都对错误情况做处理 冗余代码太多 所以在src utils request页面拦截请求统一处理 umi request 访
  • 数字电子技术基础大作业---电子表、流水灯

    数字电子技术基础大作业 电子表 流水灯 一 电子表 1 1应用的元件 555 六片74LS160N 三片74LS26D 两片74LS04D 六个个D HEX 十六进制输入的显示数码管 电阻 电容若干 1 2简单原理 用555定时器产生频率为
  • NLP中的余弦相似度 Cosine similarity 是什么,如何计算(学习心得)

    余弦相似度 Cosine similarity To measure how similar two words are we need a way to measure the degree of similarity between t
  • mysql支持copymanage方式么_PostgreSQL:Java使用CopyManager实现客户端文件COPY导入

    在MySQL中 可以使用LOAD DATA INFILE和LOAD DATA LOCAL INFILE两种方式导入文本文件中的数据到数据库表中 速度非常快 其中LOAD DATA INFILE使用的文件要位于MySQL所在服务器上 LOAD
  • python安装sklearn_如何使用VScode引入python第三方模块

    pip 是 Python 包管理工具 该工具提供了对Python 包的查找 下载 安装 卸载的功能 通过pip引入第三方模块 如果已经安装了pip 直接进入第五步 比如我要引入cv2 1 打开vscode 2 打开终端 3 输入pip in
  • ROS GDB 使用和core dump分析

    参考 http wiki ros org roslaunch Tutorials Roslaunch 20Nodes 20in 20Valgrind 20or 20GDB https blog csdn net sunxiaoju arti
  • 实现领域驱动设计----第六章

    当你决定以恶搞领域概念是否是一个值对象时 你需要考虑他是否拥有以下特征 它度量或者描述了领域中的一件东西 它可以作为不变量 它将不同的相关的属性组合成一个概念整体 当度量和描述改变时 可以用另一个值对象予以替换 它可以和其他值对象进行相等性
  • 【SpringBoot】还不会SpringBoot项目模块分层?来这手把手教你

    文章目录 前言 缘由 本文阅读时长 主要目标 试用人群 快速链接 水图 正文 1 IDEA新建项目 2 创建子模块 dependencies 依赖层 重点 3 创建子模块 main 主启动层 重点 4 创建子模块 module 模块层 5
  • Eclipse关于搭建JSP运行环境(超级详细过程附带网页地址)

    1 下载jdk 2 配置环境变量 3 下载安装Tomcat 4 下载安装Eclipse 5 配置Eclipse运行第一个JSP程序 一 下载jdk 百度地址栏搜索https www oracle com java technologies
  • js替换字符串中的空格,换行符\r\n或\n替换成

    为了让回车换行符正确显示 需要将 n 或 r n 替换成 br 同样地 将空格替换存 nbsp 这里我们通过正则表达式来替换 一 替换所有的空格 回车换行符 原始字符串 var string 欢迎访问 r nhangge com 做最好的开
  • Linux_8_磁盘存储和文件系统

    1 磁盘结构 1 1 设备文件 一切皆文件 open read write close 设备文件 关联至一个设备驱动程序 进而能够跟与之对应硬件设备进行通信 设备号码 主设备号 major number 标识设备类型 次设备号 minor
  • A*寻路算法浅析

    最近刚接触A 寻路算法 听说是一种比较高效的自动寻路的算法 当然 事实也正是如此 这么好的东西 自然是要收入囊中的 说不定什么时候也能派上用场呢 为了学习这个 也是上网找了好多资料 看了好多博客 但是貌似有些关键点没有具体说明 所以自己也是