【A星算法的优化方案】

2023-05-16

当地图很大的时候,或者使用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

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

【A星算法的优化方案】 的相关文章

  • C语言string库函数介绍(附模拟实现)

    目录 strlen 模拟实现 strcpy 模拟实现 strcat 模拟实现 strcmp 模拟实现 strncpy strncat strncmp strstr 模拟实现 strlen size t strlen const char s
  • Realsense D435i Yolov5目标检测实时获得目标三维位置信息

    文章目录 一 效果演示二 环境配置三 模型配置四 相机配置五 部分代码 六 仓库链接 一 效果演示 Colorimage Colorimage and depthimage 二 环境配置 1 一个可以运行YOLOv5的python环境 pi
  • C语言中return的各种用法

    转自 xff1a https www pinlue com article 2021 06 2614 1611638969328 html
  • 从零开始搭二维激光SLAM --- 激光雷达数据效果对比

    我们知道 xff0c 不同品牌的激光雷达产生的数据是不一样的 xff0c 那这些不同点是如何影响建图效果的呢 xff1f 这篇文章就是来分析这个问题 xff0c 将从不同光强下的点云效果 xff0c 不同夹角下的点云效果 xff0c 以及
  • 海上垂直无人机垂直起降平台

    无人机的降落要实现对飞行轨迹和飞行状态的精确控制 xff0c 对目标地点的精确定位与识别 xff0c 而海上无人机降落具有更多不确定因素 xff0c 现提出一些有效方案 xff0c 以使得无人机海上起降成为可能 无人机起降条件 xff1a
  • 开源自制6通道航模遥控器,Arduino Pro Mini NRF24L01模块

    前言 前段时间跟着LOLI大神的教程制作了LOLI三代控 xff0c 效果很好 但是 xff0c 由于LOLI三代控的接收机带有数据回传功能 xff0c 也就是接收机的无线模块也承担了发射数据功能 xff0c 所以接收机也要使用带有功率放大
  • linux下TCP/IP通讯实例

    下面是server端源码 xff1a include lt stdio h gt include lt stdlib h gt include lt string h gt include lt unistd h gt include lt
  • STM32 USART 一些问题

    SECTION 1 1 2 3 4 5 6 7 8 9 10 11 12 13
  • 数据缓冲策略 —— 无缓冲、行缓冲、全缓冲(缓冲区大小测试)

    printf打印数据时 xff0c 一般会先把数据放入C缓冲区 xff0c 然后再刷新到内核缓冲区 xff0c 最后再写入硬件 这个过程中 xff0c 数据从C缓冲区迁移到内核缓冲区的操作我们称为缓冲 xff08 也可以理解为刷新 xff0
  • K210 FreeRTOS多任务多核系统调度

    一 目的 众所周知 xff0c K210这款AI新品是一款64bit 双核芯片 xff0c 其支持裸机编程 xff0c 并且官方也提供freertos sdk xff0c 方便开发者在其上进行多任务应用开发 那么如何进行任务创建和多核开发呢
  • keil如何添加h文件_KEIL 那些编辑技巧与方法

    当然了 xff0c 很多人现在更多的是使用 VSCode 或者 SI 等软件进行编辑 xff0c 但不可否认的是 xff0c 还有很多道友还是选择 KEIL 作为编辑软件的 xff0c 本篇笔记作为一个编辑技巧的总结 关于 KEIL 软件的
  • 关于keil C51 案例 加入头文件

    1 先在工程下面建立一个 h文件 xff0c 例如delay h 在其中写入要加入的函数声明 xff0c 或者其他的一些预定义 xff1a ifndef DELAY H define DELAY H include lt reg52 h g
  • "extern C", 你真的懂了吗?

    在c 43 43 prime书中看到过 xff0c 在DLL和lib中看到过 xff0c 但是每次看过就不求甚解地一扫而过 心里知道有extern c这个语句 xff0c 却不知道该用在哪里 xff0c 又能起到什么作用 唉 xff0c 想
  • 内存或寄存器定义和赋值

    在嵌入式中 xff0c 会经常遇到寄存器 内存的数据传输 xff0c 如何向寄存器中写入数据呢 xff1f 现举例说明 xff1a define rDISRC0 volatile unsigned 0x4b000000 DMA 0 Init
  • Makefile的文件格式,详解规则

    构建规则都写在Makefile文件里面 xff0c 要学会如何Make命令 xff0c 就必须学会如何编写Makefile文件 1 概述 Makefile文件由一系列规则 xff08 rules xff09 构成 每条规则的形式如下 xff
  • 只声明而不定义变量

    如果想声明一个变量而不定义它 xff0c 就在变量前面添加关键字extern xff0c 而且不要显式地初始化变量 extern int i 声明i而非定义i extern int j 61 0 定义 int k 声明并且定义 注意 xff
  • vector 与 智能指针使用注意事项

    看以下代码 xff0c 执行时会有什么问题 xff1f include lt vector gt include lt stdio h gt include lt stdlib h gt include lt memory gt class
  • SystemV 共享内存(一)—— 共享内存的创建与释放(shmget / shmctl)

    匿名管道和命名管道都是基于文件 的进程间通信 xff0c SystemV方案是在OS内核层面 专门为进程间通信设计的一个方案 xff0c 然后通过系统调用 xff08 system call xff09 给用户提供通信接口 SystemV方
  • TTL 485 232 全双工 半双工 单工---精简总结

    全双工 xff1a 双向2车道 半双工 xff1a 双向1车道 单工 xff1a 单向车道 1 从单片机软件编程角度来说 xff0c RS232 RS485都是转换为TTL电平方式与单片机通信 xff08 CAN收发器把差分信号转化为TTL

随机推荐

  • STM32F4-ADC-常规通道-转换模式配置-总结

    STM32F4 ADC常规通道转换的模式配置 模式选择 此寄存器定义 xff1a 是否自动循环 这两个寄存器定义 xff1a Scan mode xff08 是否轮询序列 xff09 和Discontinuous mode xff08 是否
  • 单片机 裸机 架构

    以前是 while xff08 1 xff09 43 软件定时器 43 中断标志 的框架 xff0c 现在的项目我想尝试一下新的框架 xff0c 简单来说是 主状态机 43 大量子状态机 43 软件定时器 的方式 xff0c 这其中状态机和
  • USART---串口发送数据

    xfeff xfeff while USART1 gt SR amp 0X40 61 61 0 等待发送结束 解析 xff1a USART1 gt SR xff1a 串口 状态 寄存器 USART1 gt SR amp 0X40 即串口状态
  • STM32---串口初始化

    u8 USART RX BUF USART REC LEN 接收缓冲 最大USART REC LEN个字节 bit15 xff0c 接收完成标志 bit14 xff0c 接收到0x0d bit13 0 xff0c 接收到的有效字节数目 u1
  • stm32---RS485初始化

    u8 RS485 RX BUF 64 接收缓冲 最大64个字节 u8 RS485 RX CNT 61 0 接收到的数据长度 函数 xff1a RS485 Init 功能 xff1a 串口初始化配置 参数 xff1a Baud 波特率 备注
  • 定时器0,中断,控制LED闪烁(1s亮,1s灭)---2018-11-07

    include lt reg52 h gt include lt stdio h gt define uchar unsigned char define uint unsigned int sbit LED 61 P2 2 void ti
  • AM2322温湿度传感器(地址0XB8)---I2C总结(I2C_ModBus协议)

  • 数码管---共阳---共阴---段选码---位选码---总结

    共阴极 xff1a 位选为低电平 xff08 即0 xff09 选中数码管 各段选为高电平 xff08 即1接 43 5V时 xff09 选中各数码段 0 f 共阴数码管段选 表 xff0c 无小数点 xff1a unsigned char
  • ubuntu怎样通过终端打开firefox?

    1 直接输入firefox 按回车 2 首先打开火狐浏览器 xff0c 鼠标移到屏幕最顶端 xff0c 出现菜单栏 工具栏 xff0d xff0d 附加组件选项 如下图所示 也可以在火狐浏览器界面 使用快捷键 shift 43 Ctrl 4
  • 重新认识 IP地址

    目录 一 什么是网段划分 二 如何分配子网中的IP xff1f 三 IP地址的分类 1 早期划分方式 1 早期分类方式 2 早期分类的局限性 2 CIDR划分 xff08 子网掩码划分 xff09 1 基本思路 2 实现方式 四 IP地址的
  • Linux服务器下抓包工具tcpdump分析

    概述 说到抓包分析 xff0c 最简单的办法莫过于在客户端直接安装一个Wireshark或者Fiddler了 xff0c 但是有时候由于接口调用无法在客户端抓包 xff0c 只能在服务器上抓包 xff0c 这种情况下怎么办呢 xff1f 本
  • MATLAB 常用转义字符

    MATLAB常用转义字符收录如下 Single quotation mark nbsp Percent character nbsp Backslash nbsp a Alarm nbsp b Backspace nbsp f Form f
  • 利用MATLAB解决人工神经网络模拟预测问题研究

    利用MATLAB解决人工神经网络模拟预测问题研究 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 人工神经网络根据模仿人脑的工作原理抽象出来的一种算法 人工神经网络 artigicial neutral ne
  • Visual Studio 2008学习过程(之一)起步

    以前 xff0c 在使用MATLAB开发一些软件 xff0c 虽然它的数值计算方面的功能很强大 xff0c 但是界面不是很好看 xff0c 很难做出来漂亮的软件 xff0c 所以萌生了用VS和MATLAB联合编程的想法 这样可以使软件更加强
  • 如何用servlet写网页访问量计数器?

    如何用servlet写网页访问量计数器 xff1f 1 原料 l MyEclipse l Tomcat l html 2 步骤 1 新建工程 项目栏鼠标右键 New Web Project xff0c 这里我起名为 xff1a myexm4
  • 提示:请安装TCP/IP协议.error=10106。解决方案

    有朋友使用电脑的时候会出现如下错误 xff0c 如何解决该问题是本文写作的目的 提示错误 xff1a 图 1 解决 方案 xff1a 1 删除两个注册表选项 xff1b 按下windows键 43 R键 xff0c 输入regedit xf
  • 防止头文件被重复包含

    前言 为了避免同一个文件被include多次 xff0c C C 43 43 中有两种方式 xff0c 一种是 ifndef方式 xff0c 一种是 pragma once方式 方式一 xff1a ifndef SOMEFILE H 或写为
  • 有趣的网站分享——pornhub风格生成器

    寄语 要说logo设计 xff0c pornhub的logo设计让人印象深刻 xff0c 黑底白字 xff0c 配上一小撮橙色 xff0c 给人极强的冲击力 这不 xff0c 有一个有意思的程序员弄了一个网站 xff0c 专门生成pornh
  • 大小端存储问题

    1 什么是数据的高低位 数据的高位在左 xff0c 低位在右 2 什么是内存的高低位 2 什么是大端存储 小端存储 简单记就是 xff1a 小端 xff1a 低低 xff08 数据低位在内存低位 xff09 大端 xff1a 高低 xff0
  • 【A星算法的优化方案】

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