A*算法的优化

改进OpenList开启列表

使用优先队列代替List
使用有限队列能够节约对OpenList的遍历

优先队列

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;namespace YBZ.Algorithm {public class PriorityQueue<T> where T : new (){public int size;public int capacity;private T[] elements;// 是否为空public bool IsEmpty { get => size == 0; }/// 范围顶部元素public T Top { get => elements[0]; }/// 优先队列的模式private PriorityQueueMode _comparator;public enum PriorityQueueMode {less = -1, // 最小优先队列equal = 0, // 相等的排在一起greater = 1 // 最大优先队列}/// <summary>/// 以CMP(a,b) 为例:/// 当a>b时,返回1,表示放右边/// 当a==b时,返回0,表示不变///  当a<b时,返回-1,表示放左边/// </summary>private Func<T,T,int> CMP;/// <summary>/// 构造函数, 必须实现/// </summary>/// <param name="CMP"></param>/// <param name="capacity"></param>/// <param name="priorityQueueMode"></param>public PriorityQueue(Func<T,T,int> CMP, PriorityQueueMode priorityQueueMode = PriorityQueueMode.less, int capacity = 1) {this.CMP = CMP;this.size = 0; // 数组索引从0开始this.capacity = capacity;this.elements = new T[capacity];this._comparator = priorityQueueMode;}/// <summary>/// 入队/// </summary>/// <param name="value"></param>public void Push(T value) {if (size == capacity) {ExpandCapacity();}elements[size++] = value;ShiftUp();}/// <summary>/// 出队/// </summary>public void Pop() {if(size == 0) {return;}size--;Swap(ref elements[0], ref elements[size]);ShiftDown();}/// <summary>/// 清空队列/// </summary>public void Clear() {size = 0;}/// <summary>/// 返回位于Queue开始处的对象但不将其移除。/// </summary>/// <returns>返回第一个队列中元素</returns>public T Peek() {return Top;}/// <summary>/// 扩展队列的容量/// </summary>private void ExpandCapacity() {capacity = Mathf.CeilToInt(capacity * 1.5f);T[] temp = new T[capacity];for (int i = 0; i < elements.Length; i++) {temp[i] = elements[i];}elements = temp;}// 从下到上 重排序 private void ShiftUp() {int cur = size - 1 ;int parent = ( cur -1 ) >> 2;while (cur > 0) {if (CMP(elements[cur],elements[parent]) == (int)_comparator) {Swap(ref elements[cur], ref elements[parent]);cur = parent;parent = (cur - 1) >> 2;} else break;}}// 从上到下 重排序private void ShiftDown() {int cur = 0;int child = 1;while (child < size) {if (child + 1 < size && CMP(elements[child +1], elements[child]) == (int)_comparator) {child++;}if (CMP(elements[child], elements[cur]) == (int)_comparator){Swap(ref elements[child], ref elements[cur]);cur = child;child = cur << 1 + 1;} else break;}}/// <summary>/// 交换传入的两个元素/// </summary>/// <param name="lhs"></param>/// <param name="rhs"></param>private void Swap(ref T lhs,ref T rhs) {T temp = lhs;lhs = rhs;rhs = temp;}/// <summary>/// 返回队列中的所有元素,对于ToString()函数,值类型会返回值,引用类型会返回数据类型/// </summary>/// <returns></returns>public override string ToString() {string result = "";foreach (var v in elements) {result += v.ToString();}return result;}}
}

改进F = G + H启发式

加权函数

采用加权函数W(n)将启发函数改进为F = G + W * H
对于W为H的系数函数,当H越大的时候W返回的越大,要求尽快的达到目标区域;当H越小,则要求路径越准确

// 加权函数 ,具体比例可以自己决定,
public int W(int H) {int w = 1;if (w > 500) {w = 5;} else if (w > 300) {w = 4;} else if(w > 100){w = 3;}else if (w > 50) {w = 2;} else {w = 1;}return w;
}

减少拐点

同时也可以在Cost上增加系数要求尽可能走直线,使走斜线是走直线代价的两倍,但是这样只能由于特定要求,比如需要走直线的时候,否侧我认为无论是走直线,走斜线效果一样(走直线会减少邻居节点的添加)

/// <summary>
/// 额外代价
/// </summary>
/// <param name="current">当前节点</param>
/// <param name="neighbor">邻居节点</param>
/// <param name="goal">终点</param>
/// <returns></returns>
public double Cost(Node current,Node neighbor, Node goal)
{Node parent = current.parent;// 起点if (parent == null) return 0;// 走直线if (neighbor.x == parent.x || neighbor.y == parent.y) return 0;// 拐向终点的点if (neighbor.x == goal.x || neighbor.y == goal.y) return 1;// 普通拐点return 2;
}

可穿障碍物

对Cost函数上如果是障碍物就大幅度增加开销,而不是直接忽略

1.正方形节点,如果正常开销是10,那么障碍物上的开销就必须大幅度大于10, cost == 100,
2.一般还是不存在可穿障碍物

预加载邻居节点

优化Node的GetNeighbor函数使其能够在路径搜索开启前就已经完成。

using System.Linq;
public override List<NodeBase> CacheNeighbors(){return Neighbor = GridManager.Instance.Tiles.Where(t => Coords.GetDistance(t.Value.Coords) == 1).Select(t => t.Value).ToList();}

JPS(Jump Point Search)

跳点搜索,优先走斜线,尽可能才减掉不需要的邻居节点
相对于矩形节点,走直线只会得到三个新的邻居节点
走斜线,就能得到五个新的邻居节点,能够快速增加自己节点搜索

Map优化

控制维度

控制Map的大小

分层优化(预加载路径)

1.将大面积的的地区先作为一个节点,比如从莫斯科到北京就要求先从俄罗斯到中国,在这过程中逐步缩小范围,莫斯科到中国边境,再从边境到北京市,在到目的地。
2.对于俄罗斯到中国的路径,采用预加载模式,每次从俄罗斯到中国都采用这条路径。
3.调用前对比,大致对比开销,如果开销大幅度低于预加载好的路径,则走自己计算的路径

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

50吨收费站生活一体化污水处理设备厂家价格低

50吨收费站生活一体化污水处理设备厂家价格低 设备工艺说明 污水处理设备主要用于生活污水和与之类似的工业有机废水的处理&#xff0c;其主要处理方法是采用目前较为成熟的生化处理技术—生物接触氧化&#xff0c;水质设计按一般生活污水水质设计计算&#xff0c;按BOD5平均20…

【图像分类】CNN + Transformer 结合系列.4

介绍两篇利用Transformer做图像分类的论文&#xff1a;CoAtNet&#xff08;NeurIPS2021&#xff09;&#xff0c;ConvMixer&#xff08;ICLR2022&#xff09;。CoAtNet结合CNN和Transformer的优点进行改进&#xff0c;ConvMixer则patch的角度来说明划分patch有助于分类。 CoAtN…

GitHub不能正常打开以及CSS样式加载不成功的解决方案

大家好&#xff0c;今天分享GitHub不能正常打开以及CSS样式加载不成功的解决方案。当GitHub在没有“科学上网”的情况下&#xff0c;不能正常打开时&#xff0c;最直接的检测方法就是 ping 掉包情况。&#xff08;当然还有其它抓包的方法&#xff09;。通过 ping github.com可见…

专业商城财务一体化-线上商城+进销存管理软件,批发零售全行业免费更新

订货流程繁琐&#xff1f;订单处理效率低&#xff1f;小程序商城与进销存系统不打通&#xff1f;数据需要手动输入同步&#xff1f;财务与的结算对账需要大量手工处理&#xff1f;零售批发从业者&#xff0c;如何你也有以上烦恼&#xff0c;可以看看进销存小程序订货商城&#…

python几岁可以学零基础,python多大的孩子可以学

大家好&#xff0c;小编为大家解答多大的孩子可以学python的问题。很多人还不知道学python多大年龄可以学&#xff0c;现在让我们一起来看看吧&#xff01; python编程是现在很多孩子接触编程的好选择&#xff0c;它能够给孩子带来容易入门的效果。那么&#xff0c;python编程少…

Linux命令(63)之ulimit

linux命令之ulimit 1.ulimit介绍 linux命令ulimit是用来控制执行程序的资源 2.ulimit用法 ulimit [参数] ulimit参数 参数说明-n单个程序可以打开的最大文件描述符-u单个程序可以使用的最大进程数-d显示程序数据节区的最大值-m显示程序使用memory的最大上限-a显示当前资源设…

基于星火和Gradio的聊天机器人

星火大模型官网&#xff1a;https://xinghuo.xfyun.cn/ 1 创建虚拟环境&#xff08;windows&#xff09; conda create -n Gradio python3.8 pip install gradio 中间遇到os报错&#xff0c;解决方案&#xff1a; pip install aiofiles23.2.1 2 代码 SparkDesk.py&#xff1a…

安卓:LitePal操作数据库

目录 一、LitePal介绍 常用方法&#xff1a; 1、插入数据&#xff1a; 2、更新数据&#xff1a; 3、删除数据&#xff1a; 4、查询数据&#xff1a; 二、LitePal的基本用法&#xff1a; 1、集成LitePal&#xff1a; 2、创建LitePal配置文件&#xff1a; 3、创建模型类…

[保研/考研机试] 括号匹配问题 C++实现

题目描述&#xff1a; 在某个字符串(长度不超过100)中有左括号、右括号和大小写字母&#xff1b;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序&#xff0c;找到无法匹配的左括号和右括号&#xff0c;输出原来的字符串&am…

qemu 虚拟化

一、介绍QEMU Qemu是种非常古老的虚拟化技术&#xff0c;用于虚拟化系统组件并在其上运行多种CPU架构的程序或操作系统。 借助KVM&#xff0c;Qemu可以通过使用基于硬件的虚拟化来获得超快的计算速度。QEMU充当硬件供应商&#xff0c;KVM是CPU。KVM驻留在Linux内核中&#xff0…

数据挖掘具体步骤

数据挖掘具体步骤 1、理解业务与数据 2、准备数据 数据清洗&#xff1a; 缺失值处理&#xff1a; 异常值: 数据标准化&#xff1a; 特征选择&#xff1a; 数据采样处理&#xff1a; 3、数据建模 分类问题&#xff1a; 聚类问题&#xff1a; 回归问题 关联分析 集成学习 image B…

美国Linux服务器安装Grafana和配置zabbix数据源的教程

美国Linux服务器的Grafana工具是跨平台、开源、时序和可视化面板Dashboard监控平台工具&#xff0c;是在日常管理中帮忙提高效率的实用工具&#xff0c;可以通过将采集的美国Linux服务器系统数据查询后&#xff0c;进行可视化的展示及通知&#xff0c;本文小编就来介绍下美国Li…

异步回调中axios,ajax,promise,cors详解区分

Ajax、Promise和Axios之间的关系是&#xff0c;它们都是用于在Web应用程序中发送异步HTTP请求的JavaScript库&#xff0c;但它们有不同的实现方式和用法。 Ajax是一种旧的技术&#xff0c;使用XMLHttpRequest对象来向服务器发送异步请求并获取响应。它通常需要手动编写回调函数…

Windows安装Redis

自己电脑做个测试&#xff0c;需要用到Redis&#xff0c;把安装过程记录下&#xff0c;方便有需要的人 1、找到下载地址&#xff1a;Releases microsoftarchive/redis GitHub Windows的Redis需要到GitHub上下载&#xff1a; 2、下载完后设置密码&#xff0c;打开文件夹&…

Java | 异常处理

目录 一、异常概述 二、异常的抛出与捕捉 2.1 抛出异常 2.2 捕捉异常 2.2.1 try-catch语句块 2.2.2 finally语句块 三、Java常见的异常类 四、自定义异常 五、在方法中抛出异常 5.1 使用throws关键字抛出异常 5.2 使用throw关键字抛出异常 六、运行时异常 七、异…

idea创建SpringBoot项目

项目命名规范 项目名全部小写。包名全部小写。 一、点击 Create New Project 二、选择 Maven 点击Next 三、定义项目名称/组 四、定义项目名称 项目存储路径 五、完成创建 六、配置Maven 没配置之前 配置Maven&#xff1a; File > settings...> Build Execution Deplo…

Git出错。fatal: unable to access Failed to connect to github.com

git时遇到fatal: unable to access ‘https://github.com/jdbsid/WPFLearning.git/’: Failed to connect to github.com port 443 after 21072 ms: Couldn’t connect to server git bash输入&#xff1a; git config --global --unset http.proxygit config --global --uns…

C#使用OpenCv(OpenCVSharp)图像局部二值化处理实例

本文实例演示C#语言中如何使用OpenCv(OpenCVSharp)对图像进行局部二值化处理。 目录 图像二值化原理 局部二值化 自适应阈值 实例 效果

[保研/考研机试] KY129 简单计算器 浙江大学复试上机题 C++实现

描述 读入一个只包含 , -, *, / 的非负整数计算表达式&#xff0c;计算该表达式的值。 输入描述&#xff1a; 测试输入包含若干测试用例&#xff0c;每个测试用例占一行&#xff0c;每行不超过200个字符&#xff0c;整数和运算符之间用一个空格分隔。没有非法表达式。当一行中…

uniapp 微信小程序实现监听屏幕左右滑动实现tab标签切换效果

需求背景&#xff1a; 实际的项目开发之中&#xff0c;有很多所谓的奇葩需求&#xff0c;当工程量相对较大的时候去更换组件会显得特别麻烦和费时。我这次的需求因为某些特殊原因&#xff0c;更换组件后也无法实现需要达到的效果&#xff0c;所以最后只能监听滑动事件&#xff…