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*寻路算法浅析 的相关文章

  • 如何验证无锁算法?

    从理论上讲 至少应该可以对无锁算法进行暴力验证 只有这么多的函数调用组合 是否有任何工具或正式推理过程可以实际证明无锁算法是正确的 理想情况下它还应该能够检查竞争条件和 ABA 问题 注意 如果你知道一种方法来证明一点 例如 只证明它不受
  • 比 in_array 更快?

    我需要将一个值与一组数组进行比较 但是 我需要比较 foreach 中的多个值 如果使用 in array 它可能会很慢 非常慢 有没有更快的替代方案 我当前的代码是 foreach a as b in array b array 谢谢 你
  • 算法 - 如何有效删除列表中的重复元素?

    有一个list L 它包含以下元素任意类型each 如何有效删除此类列表中的所有重复元素 必须保留订单 只需要一个算法 因此不允许导入任何外部库 相关问题 在Python中 从列表中删除重复项以使所有元素都是唯一的最快算法是什么在维持秩序的
  • 找到不(必要)与二进制矩阵中的图像边界对齐的最大矩形

    我在用这个解决方案 https stackoverflow com questions 2478447 find largest rectangle containing only zeros in an nn binary matrix在
  • 将整数列表划分为总和相等的 K 个子列表

    类似的问题还有1 https stackoverflow com questions 27322804 partition of a set into k disjoint subsets with equal sum and 2 http
  • 寻找下一个素数的最佳方法(Java)

    我被要求编写一个程序以最佳方式找到下一个素数 我编写了这段代码 但找不到最佳答案 有什么建议么 public static int nextPrime int input input now find if the number is pr
  • 识别鼠标移动的算法

    我想知道是否有任何研究 算法可以指定鼠标在识别 等字符时的偏差量使用鼠标绘制 某种光学字符识别 但可能是一个更简单的版本 是否有某种算法可以让我说用户绘制的问号确实是一个问号 而不是其他具有一定准确性的东西 就像 Windows 平板电脑软
  • 为什么《破解编码面试》这个例子的时间复杂度是O(k c^k)?

    该问题来自 破解编码面试 第 6 版 问题 V1 11 以下代码打印长度为 k 的所有字符串 其中字符 是按排序顺序排列的 它通过生成所有长度的字符串来做到这一点 k 然后检查每个是否已排序 什么是运行时间 package QVI 11 P
  • 图像算法上的物体计数

    我又接到学校任务了 这次 我的老师给我的任务是创建算法来计算图片上有多少只鸭子 该图与此类似 我想我应该使用模式识别来搜索上面有多少只鸭子 但我不知道每只鸭子适合哪种图案 我认为你可以通过分割鸭嘴并计算鸭嘴的数量来解决这个问题连接的组件 h
  • 如何设计一种算法来计算倒数式数学数字难题

    我一直想这样做 但每次我开始思考这个问题时 它的指数性质都会让我大吃一惊 我希望能够理解的问题解决器和代码是针对倒计时数学问题的 给定一组数字 X1 到 X5 计算如何使用数学运算将它们组合起来生成 Y 您可以应用乘法 除法 加法和减法 那
  • 运行时间为 O(n) 且就地排序的排序算法

    有没有运行时间为O n 并且还分类到位 在某些情况下 最好的情况是 O n 但这可能是因为项目集合已经排序 你正在看 O nlogn 一些较好的平均值 话虽如此 排序算法的 Wiki 还是相当不错的 有一个表格比较了流行的算法 说明了它们的
  • 简单的排名算法

    我需要创建一个民意调查 按照项目的好坏顺序创建一个排名列表 我打算向每个用户展示两个项目 让他们选择一个他们认为更好的项目 然后多次重复这个过程 它有点类似于您在社交网络电影 我应该如何根据收到的答案对项目进行排名 看着那 这ELO国际象棋
  • 检查有效的 IMEI

    有人知道如何检查有效的 IMEI 吗 我找到了一个可以检查此页面的功能 http www dotnetfunda com articles article597 imeivalidator in vbnet aspx http www do
  • 当给定块大小时反转单链表

    有一个单连接链表 并给出了块大小 例如 如果我的链表是1 gt 2 gt 3 gt 4 gt 5 gt 6 gt 7 gt 8 NULL我的块大小是4然后反转第一个4元素 然后是第二个 4 个元素 问题的输出应该是4 gt 3 gt 2 g
  • heapq.nlargest 的时间复杂度是多少?

    我在看演讲者说 获得t列表中最大的元素n元素可以在O t n 这怎么可能 我的理解是创建堆将是O n 但是复杂度是多少nlargest本身就是O n t or O t 实际的算法是什么 在这种情况下 说话者是错误的 实际成本是O n log
  • 重写修改后的 goto 语义的算法

    我有一大堆使用旧的自行设计的脚本语言编写的遗留代码 我们将它们编译 翻译成 javascript 该语言有条件跳转 跳转到标签 与普通 goto 语句的区别在于 不可能向后跳转 该语言中没有嵌套的 if 语句或循环 由于 javascrip
  • 我应该对算法使用递归还是记忆化?

    如果我可以选择使用递归或记忆来解决问题 我应该使用哪一个 换句话说 如果它们都是可行的解决方案 因为它们提供了正确的输出并且可以在我正在使用的代码中合理地表达 那么我什么时候会使用其中一个而不是另一个 它们并不相互排斥 您可以同时使用它们
  • 优化计算中使用的 # 个线程的算法

    我正在执行一个操作 我们将其称为CalculateSomeData CalculateSomeData 在连续的 代 中运行 编号为 1 x 整个运行中的代数由CalculateSomeData 的输入参数固定 并且是先验已知的 完成一次生
  • 颜色逻辑算法

    我们正在构建一个体育应用程序 并希望将团队颜色融入到应用程序的各个部分 现在 每个团队都可以使用几种不同的颜色来表示 我想做的是执行检查以验证两个团队颜色是否在彼此一定的范围内 这样我就不会显示两个相似的颜色 因此 如果团队 1 的主要团队
  • 在一个区域中拟合二维多边形的算法?

    这有标准吗 算法名称 说 我有 10 个不同大小的多边形 我有一个特定大小的区域 我想知道如何填充该区域中的最多多边形 以及它们是如何拟合的 笔记 多边形可以根据限制集进行旋转 一个可能的名称是包装问题 http en wikipedia

随机推荐

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