当地图很大的时候,或者使用A星算法的寻路频率很高的时候,普通的A星算法就会消耗大量的CPU性能急剧下降,普通的A星性能还是不过关。接下来我们讲讲A星寻路在遇到性能瓶颈时的优化方案。

一、长距离导航

当距离很大,中间有很多障碍物时,A星的算法就会遇到瓶颈,不断加入的可行走点使得排序速度越来越慢,最后可能造成CPU阻塞无法动弹。

当寻路距离太大时怎么办?

其实路径不是非得实时计算出来才好,我们可以把一些常用的路径,在离线下算好放在数据文件中,游戏开启时放在内存里,当需要寻路到那个节点或者那个节点附近时,就可以取出来直接使用,而不再需要计算。

比如 A到B 我们已经算法路径并存放在了内存里,当我们在A附近,要寻路到B附近时,就可以先寻路到A,再调出A到B的路径,再计算B到目的的路径。

以这种方式来规避一些计算量特别大,或者计算频率特别高的寻路算法调用,在大型世界的RPG游戏里特别常用。

另一种方法为制作导航点的方式。什么是导航点呢?就是去目的地的必经的点位。

比如在一座城市里,有4个出口点,这个4个出口点就可以称为导航点,去目的地的路上肯定会经过这4个点的其中一个,我们在寻路时可以先寻找到最近的一个出口的导航点,当到达导航点后,再次寻找到目的地去的路径,有可能在这条路径上,还有一些导航点,继续寻找最近的导航点,依次类推,直到没有导航点可寻时,则直接寻路到目的地。

二、A星的排序算法优化

每次插入open列表的点后,open就不再是有序的队列了,所以每次去拿最小值时都需要重新排序。排序的时间消耗随着队列长度的增大而增大,其实有很大一部分A星的性能消耗都在排序上。

那么是不是可以不排序,其实可以不排序,而使用找到插入位置并插入的方法,让队列永远保持有序状态。

因为open队列在插入前是有序的,所以我们可以选用二分查找算法来找到插入的位置。

每次插入时都使用二分查找算法查找插入点,那么每次的插入复杂度为O(logN),比快排一次的O(NlogN)要快很多。

三、优化排序判断依据的预测值计算方法

前面用图所举的例子中,都是以当前点p与终点e之间的距离来作为预测值,这种方法简单但也不科学,导致A星寻找更好的点位时总是要绕很大的弯路。

我们可以改变一下这个策略,选用一个更科学的方法, F 预测值= G 当前最近步数 + H 预测当前点到终点的步数 的方法。

F 为预测值,G为起点s到当前点p的最近步数,H为当前点p到终点e的预测值,它们相加为F预测值。

其中G应该是已经计算好并放入节点中的值,该值就是计算过程中起点s到当前点的步数。我们可以把每步计算好的步数都放入节点中,以待需要计算时使用。

这个方法相当于,原来只关注当前点到终点的距离,变为关注起点s经过当前点p路径到终点e的距离,虽然还是贪婪的简单预测算法,但比起原来只关注当前点p与终点e的距离,更加科学化,能更快的找到更好更近的点位。

为什么要改善这个预测值,改善预测值有什么意义呢?

其实预测值的计算方法代表了在寻路过程中的走法,如果预测值只关注在于终点距离最近的点上,那么在寻路过程中的选择点位的顺序就会偏向于与终点更近的点。而如果预测值计算公式,关注的是整个距离较近的点位上,那么在寻路过程中在选择点位上也就会偏向整条路径短的方向上去靠。

四、多次频繁A星寻路的优化

多次频繁寻路中,对A星算法中每个运算,每行代码的运算细节都会有比较重大的考验。

比如我们在查看一个节点是否为被取过的节点,即是否为Close,很多人都会在Close里取寻找该节点是否存在,这个操作明显就没有考虑到性能的消耗,要在Close列表中找节点,就相当于遍历一遍所有已经找过的节点,Close里的节点越多,越浪费CPU,而且是不只一次浪费,每个循环都会浪费一次,性能消耗巨大。

因此我们通常的做法是把节点作为一个实例,在实例中添加IsClose的变量,来判断是否被取过,或者说是否Close。

但这种方法还是不够,因为IsClose变量是要初始化的,每次寻路都要将前面寻路过的痕迹抹去才能开始全新的寻路过程。

这就是又一个被很多人忽视的初始化的性能消耗,每次在A星寻路开始前,需要将IsClose的变量初始化为false,就需要遍历整个数据来初始化。

每次都要遍历整个数据的话,A星算法无论优化的多快都无济于事了,因为初始化的性能消耗就已经将A星的性能消耗完全盖掉了。如果初始化的性能消耗需要遍历整个数据,那么优化A星算法的意义何在。

其实可以用一个变量就能判断IsClose的方法,无需初始化。

我们可以在寻路类中设置一个属性变量FindIndex,或者专门为寻路服务的静态变量也可以,而每个寻路节点中也存有一个变量FindIndex,每次寻路前都对FindIndex++,在判断IsClose时,当节点中的FindIndex与寻路类中FindIndex一致时说明已经被当次寻路算法取出过,否则两者不一样,说明这个节点没有被取出过,当节点被取出时,节点里的FindIndex则设置为当前寻路类中的FindIndex值,以表明该节点已经被这次寻路算法取出过。

用一个变量和整数的比较就能知道IsClose的结果,省去了巨量的初始化操作。

在A星算法这种经常用频繁用的算法中,一个小小的性能消耗就能放大很多倍,特别注意调用的函数的复杂度,公式的复杂度,以及运算的优化,尽量做到能不调用函数的不调用函数,能简化公式的尽量简化公式,能用&|<>位运算符号代替加减乘除的尽量用位运算代替,节省A星算法的性能开销。

我也看过所谓的B星算法过程,其实世上没有B星,所谓的B星其实就是我们A星的优化版本,而且互联网中所阐述的B星算法存在一定几率无法寻到路径的问题,即它只关注所谓的‘前方‘,而忽略了其实’后方‘也有路,如果只有后方有路时,B星就无法找到路径。

转载自:https://www.jianshu.com/p/0e696bf0d0b8

【A星算法的优化方案】相关推荐

  1. MySQL ALGORITHM = UNDEFINED/MERGE/TEMPORTARY 详解视图的三种算法与优化方案

    CREATE [ALGORITHM = {MERGE | TEMPTABLE | UNDEFINED}] VIEW [database_name].[view_name] AS [SELECT sta ...

  2. 计算机程序框图当n200,【优化方案】2020高考数学总复习 9-11章算法与程序框图课时卷 北师大版(通用)...

    <[优化方案]2020高考数学总复习 9-11章算法与程序框图课时卷 北师大版(通用)>由会员分享,可在线阅读,更多相关<[优化方案]2020高考数学总复习 9-11章算法与程序框图 ...

  3. 动态规划算法之资源分配问题及其空间优化方案

    资源分配问题:某厂根据计划安排,拟将n台相同的设备分配给m个车间,各车间获得这种设备后,可以为国家提供盈利Ci j(i台设备提供给j号车间将得到的利润,1≤i≤n,1≤j≤m).问如何分配,才使国家得 ...

  4. 神经网络参数优化算法,神经网络参数优化方案

    <matlab神经网络30个案例分析> 第13章的SVM参数优化用的是什么方法? 代码如下 谷歌人工智能写作项目:神经网络伪原创 跪求bp神经网络输入层16个,输出层6个.关于爆破参数优化 ...

  5. 干货:嵌入式C语言源代码优化方案(非编译器优化)

    点击上方"大鱼机器人",选择"置顶/星标公众号" 福利干货,第一时间送达! 1.选择合适的算法和数据结构 选择一种合适的数据结构很重要,如果在一堆随机存放的数中 ...

  6. 地图信息,障碍判断以及寻路算法(A星算法,B星算法和蚁群算法等)

    一.广度优先遍历和深度优先遍历 在学习寻路算法之前,我们先来了解一下广度优先遍历和深度优先遍历. 什么是广度优先遍历? 广度优先遍历(breadth first search)是一个万能的算法. 广度 ...

  7. oracle星型查询,优化星型查询

    当你使用星型查询时,你需要考虑以下两点: 调整星型查询 使用星型转换 调整星型查询为了获得星型查询的最佳性能,遵循一些基本准则是非常重要的:应该为事实表的每一个外键列都创建位图索引. 初始化参数STA ...

  8. 动态规划算法的优化技巧

    动态规划是信息学竞赛中一种常用的程序设计方法,本文着重讨论了运用动态规划思想解题时时间效率的优化.全文分为四个部分,首先讨论了动态规划时间效率优化的可行性和必要性,接着给出了动态规划时间复杂度的决定因 ...

  9. [译]解密 Uber 数据科学团队路径选择算法的优化之路

    概述 一键用车现在已经烂大街,但是 Uber 简单的界面下又隐藏着怎样复杂的后端架构和服务呢?这些复杂的路径规划和订单匹配算法又是如何让车找到人,将人送到目的地的呢?现在让我们揭开Uber App这神 ...

最新文章

  1. Laravel Redis操作大全
  2. HDOJ 1157 HDU 1157 Who's in the Middle ACM 1157 IN HDU
  3. c语言一行黑白相间的瓷砖,C语言编程练习15:贴瓷砖
  4. Codeforces Round #648 (Div. 2)题解 A-D
  5. 量化因果涌现表明:宏观可以战胜微观
  6. 非程序员如何使用 Git——版本控制你的生活
  7. JVM-07垃圾收集Garbage Collection【GC日志分析】
  8. 广西区计算机一级全称是,计算机一级考试(广西区)历年真题-20210412075414.pdf-原创力文档...
  9. 2. Add Two Numbers 两数相加
  10. 24 SD配置-主数据-维护客户主记录中的保留字段
  11. poj2240 Floyd
  12. Java泛型报错的解决办法
  13. 获得碳中和认证的六个步骤
  14. 哈夫曼编码(Huffman Coding)多图详细解析
  15. 用moment将时间戳格式化为周几 几月几日
  16. lisp 非对称缓和曲线_利用AutoLISP语言绘制带缓和曲线的铁路曲线平面图
  17. 论文笔记Improving Multi-hop Knowledge Base Question Answering by Learning Intermediate Supervision Signa
  18. python怎样算入门_python初学者怎么入门
  19. 一次性剪辑多个视频,在视频背景添加相同图片
  20. 微信获取scheme码提示invalid weapp pagepath rid: 6397ef44-0f537d77-76155114

热门文章

  1. STM32CubeMX学习笔记(20)——DAC接口使用(输出正弦波)
  2. Nebula Graph
  3. 有限差分法电磁场matlab,有限差分法的分析电磁场边值问题(定稿).doc
  4. python接水果游戏代码_Python开发接水果小游戏编程
  5. 网络工程基础——路由器路由器划分权限
  6. w10 计算机配置管理模板,让Win10系统界面回归朴实的技巧
  7. 第四代计算机网络是高速互联的什么网,宽带接入网竞赛试题(选择题300道,判断题150道,填空题250道)...
  8. 新手入门保姆级教程,Linux平台和手机端SDK,基于Opencv、MNN、NCNN
  9. CASS或BMF软件命令栏不见了如何调出
  10. AcWing 188. 武士风度的牛(BFS,C++)