【路径规划】A*算法 Java实现

A*(A-Star)算法是一种广泛使用的寻路算法,尤其在计算机科学和人工智能领域。

算法思想

通过评估函数来引导搜索过程,从而找到从起始点到目标点的最短路径。评估函数通常包括两部分:一部分是已经走过的实际距离,称为g值;另一部分是对当前位置到目标位置的估计距离,称为h值。A*算法每次选择g值加上h值最小的节点作为下一个要访问的节点,直到找到目标节点为止。

A*算法维护一个开放列表和一个关闭列表。开放列表包含待访问的节点,而关闭列表包含已经访问过的节点。算法从起始节点开始,将其加入开放列表。然后,算法从开放列表中选择一个评估函数值最小的节点进行扩展,将其邻居节点加入开放列表,并将当前节点移入关闭列表。算法不断重复这个过程,直到找到目标节点或者开放列表为空。

在这里插入图片描述

代码实现

单元格类实现

/*** 表示地图上的一个单元格*/
class Cell {int i, j; // 单元格的行和列索引int f, g, h; // f值、g值和h值Cell parent; // 父节点boolean closed, visited; // 是否关闭和是否访问过// 构造函数public Cell(int i, int j) {this.i = i;this.j = j;this.f = 0;this.g = 0;this.h = 0;this.parent = null;this.closed = false;this.visited = false;}
}

A*算法类实现

/*** A*算法实现类*/
public class AStar {private int[][] map; // 地图private int startI, startJ; // 起始位置的行和列索引private int endI, endJ; // 目标位置的行和列索引private List<Cell> openList = new ArrayList<>(); // 开放列表private static final int DIAGONAL_COST = 14; // 对角线移动的代价private static final int VERTICAL_HORIZONTAL_COST = 10; // 垂直或水平移动的代价// 构造函数public AStar(int[][] map, int startI, int startJ, int endI, int endJ) {this.map = map;this.startI = startI;this.startJ = startJ;this.endI = endI;this.endJ = endJ;}/*** 搜索路径*/public void search() {// 创建起始和目标单元格对象Cell start = new Cell(startI, startJ);Cell end = new Cell(endI, endJ);// 将起始单元格添加到开放列表中openList.add(start);while (!openList.isEmpty()) {// 按照f值对开放列表进行排序,选择f值最小的单元格作为当前单元格Collections.sort(openList, Comparator.comparingInt(cell -> cell.f));Cell current = openList.get(0);// 如果当前单元格是目标单元格,则找到路径,打印路径并返回if (current.i == end.i && current.j == end.j) {printPath(current);return;}// 从开放列表中移除当前单元格,并将其标记为已关闭openList.remove(current);current.closed = true;// 遍历邻居单元格for (int[] direction : directions) {int newI = current.i + direction[0]; // 计算新的行索引int newJ = current.j + direction[1]; // 计算新的列索引// 如果新的索引越界,则跳过该邻居单元格的处理if (newI < 0 || newI >= map.length || newJ < 0 || newJ >= map[0].length) {continue;}// 如果邻居单元格是障碍物,则跳过该邻居单元格的处理if (map[newI][newJ] == 1) {continue;}Cell neighbor = new Cell(newI, newJ);if (neighbor.closed) { // 已关闭的单元格处理continue;}// 计算代价和启发式函数值int g = current.g + getCost(current, neighbor);int h = heuristic(neighbor, end);if (!neighbor.visited) { // 未访问过的邻居单元格处理neighbor.visited = true;neighbor.parent = current; // 设置父节点neighbor.g = g; // 设置g值neighbor.h = h; // 设置h值neighbor.f = g + h; // 设置f值openList.add(neighbor); // 添加到开放列表中} else if (g < neighbor.g) { // 已访问过的邻居单元格,且新的路径代价更小处理neighbor.parent = current; // 更新父节点neighbor.g = g; // 更新g值neighbor.f = g + neighbor.h; // 更新f值}}}System.out.println("No path found."); // 没有找到路径的情况处理}// 计算从当前单元格到邻居单元格的代价private int getCost(Cell current, Cell neighbor) {int dx = Math.abs(current.i - neighbor.i);int dy = Math.abs(current.j - neighbor.j);if (dx == 1 && dy == 1) { // 对角线移动return DIAGONAL_COST;} else { // 垂直或水平移动return VERTICAL_HORIZONTAL_COST;}}// 启发式函数,计算当前单元格到目标单元格的预计代价private int heuristic(Cell current, Cell goal) {int dx = Math.abs(current.i - goal.i);int dy = Math.abs(current.j - goal.j);return dx + dy; // 使用曼哈顿距离作为启发式函数}// 打印路径private void printPath(Cell end) {List<Cell> path = new ArrayList<>();Cell current = end;while (current != null) {path.add(current);current = current.parent;}Collections.reverse(path);System.out.print("Path: ");for (Cell cell : path) {System.out.print("(" + cell.i + "," + cell.j + ") ");}System.out.println();}// 八个方向的移动向量private static final int[][] directions = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};public static void main(String[] args) {int[][] map = {{0, 0, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 0, 0, 0, 0}}; // 定义地图,0表示可通过,1表示障碍物//打印一次地图用于观察for (int[] arr : map) {for (int x : arr) {System.out.print(x + "   ");}System.out.println();}AStar astar = new AStar(map, 0, 0, 4, 4); // 创建A*对象,设置起始位置和目标位置astar.search(); // 搜索路径}
}

以下是它的优点和缺点:

优点

  • 完整性:A* 算法总是能找到从起始点到目标点的最短路径,只要这样的路径存在。
  • 最优性:A* 算法找到的路径是最短的,或者说代价最小的。
  • 启发式搜索:A* 算法采用启发式函数来引导搜索过程,提高了搜索效率。

缺点

  • 空间复杂度较高:A* 算法需要存储搜索过程中的所有节点,因此在复杂地图或大数据集上运行时,可能会占用大量内存。
  • 时间复杂度较高:尽管 A* 算法比许多其他搜索算法更高效,但在大规模问题中,搜索时间可能会变得很长。
  • 对启发式函数依赖性强:A* 算法的效率在很大程度上取决于选择的启发式函数。如果启发式函数选择不当,可能会导致搜索效率低下。

以上就是 A* 算法的优缺点,需要根据具体的应用场景来决定是否使用 A* 算法。

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

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

相关文章

Linux docker 安装 部署

docker 安装 linux系统离线安装docker 如何使用docker部署c/c程序 常用命令 给予 docker 访问 gui 的权限 在 /etc/profile 末尾添加 if [ "$DISPLAY" ! "" ] thenxhost fi在执行 更新 source /etc/profiledocker下载镜像 docker search gcc #搜索d…

C#的DataGridView数据控件(直接访问SQL vs 通过EF实体模型访问SQL)

目录 一、在DataGridView控件中显示数据 1.直接编程访问SQL &#xff08;1&#xff09;源码 &#xff08;2&#xff09;生成效果 2.通过EF实体模型访问SQL &#xff08;1&#xff09;源码 &#xff08;2&#xff09;生成效果 二、获取DataGridView控件中的当前单元格 …

文献阅读(207)FPGA HBM

题目&#xff1a;HBM Connect: High-Performance HLS Interconnect for FPGA HBM时间&#xff1a;2021会议&#xff1a;FPGA研究机构&#xff1a;UCLA Jason Cong 题目&#xff1a;Demystifying the Memory System of Modern Datacenter FPGAs for Software Programmers throug…

K-Means和KNN

主要区别 从无序 —> 有序 从K-Means —> KNN KNN&#xff1a;监督学习&#xff0c;类别是已知的&#xff0c;对已知分类的数据进行训练和学习&#xff0c;找到不同类的特征&#xff0c;再对未分类的数据进行分类。K-Means&#xff1a;无监督学习&#xff0c;事先不知道…

【Ubuntu18.04】激光雷达与相机联合标定(Livox+HIKROBOT)(一)相机内参标定

LivoxHIKROBOT联合标定——相机内参标定 引言1 海康机器人HIKROBOT SDK二次开发并封装ROS1.1 介绍1.2 安装MVS SDK1.3 封装ROS packge 2 览沃Livox SDK二次开发并封装ROS3 相机雷达联合标定——相机内参标定3.1 环境配置3.1.1 安装依赖——PCL 安装3.1.2 安装依赖——Eigen 安装…

快捷键记录

文章目录 ctrlaltashftwinsWinRCtrlc和CtrlvCtrl -Xshell的复制粘贴ctrlalt&#xff08;鼠标跳出&#xff09;ctrl alt T ctrlalta 这是QQ/TIM的屏幕截图快捷键。截图成功后&#xff0c;会有一栏导航&#xff0c;可以对图片进行勾画、模糊、绘画、标号、撤回、翻译、提取文…

百度文心一言4.0抢先体验教程!

&#x1f341; 展望&#xff1a;关注我, AI学习之旅上&#xff0c;我与您一同成长&#xff01; 一、 引言 想快速体验文心一言4.0&#xff0c;但又觉得技术难度太高&#xff1f;别担心&#xff0c;我来手把手教你&#xff01; &#x1f680; 10月17日&#xff0c;文心一言4.0…

【Overload游戏引擎细节分析】PBR材质Shader

PBR基于物理的渲染可以实现更加真实的效果&#xff0c;其Shader值得分析一下。但PBR需要较多的基础知识&#xff0c;不适合不会OpenGL的朋友。 一、PBR理论 PBR指基于物理的渲染&#xff0c;其理论较多&#xff0c;需要的基础知识也较多&#xff0c;我在这就不再写一遍了&…

Centos使用war文件部署jenkins

部署jenkins所需要的jdk环境如下&#xff1a; 这里下载官网最新的版本&#xff1a; 选择jenkins2.414.3版本&#xff0c;所以jdk环境最低得是java11 安装java11环境 这里直接安装open-jdk yum -y install java-11-openjdk.x86_64 java-11-openjdk-devel.x86_64下载jenkins最新…

leetcode第80题:删除有序数组中的重复项 II

题目描述 给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 …

人性与理性共赢,真心罐头跃过增长的山海关

在北方不少地方&#xff0c;黄桃罐头是一种抚慰人心的力量。从大连起家&#xff0c;用真材实料打动人心的真心罐头&#xff0c;在朝着国民品牌前进的路上&#xff0c;需要更透彻地洞悉“人性”。 ”人的因素影响太大。我们希望可以告别个人英雄主义&#xff0c;用流程来保证可…

139.【JUC并发编程-04】

JUC-并发编程04 (八)、共享模型之工具1.线程池(1).自定义线程池_任务数小于队列容量(2).自定义线程池_任务数大于队列容量(3).自定义线程池_拒绝策略 2.ThreadPoolExecutor(1).线程池状态(2).构造方法(3).newFixedThreadPool (固定大小线程池)(4).newCachedThreadPool (缓存线程…

设树B是一棵采用链式结构存储的二叉树,编写一个把树 B中所有结点的左、右子树进行交换的函数 中国科学院大学2015年数据结构(c语言代码实现)

本题代码如下 void swap(tree* t) {if (*t)// 如果当前节点非空 {treenode* temp (*t)->lchild;// 临时存储左子节点 (*t)->lchild (*t)->rchild;// 将右子节点赋值给左子节点(*t)->rchild temp;// 将临时存储的左子节点赋值给右子节点 swap(&(*t)->l…

【ModbusTCP协议】

ModbusTCP协议 一、搭建一个ModbusTCP环境二、ModbusTCP通信协议报文格式ModbusTCP的特点 一、搭建一个ModbusTCP环境 搭建一个ModbusTCP环境 1、使用ModbusSlave 2、可以用西门子PLC来做 使用西门子搭建ModbusTCP环境&#xff0c;就需要先搭建一个西门子PLC仿真环境 下载软件P…

NSS [SWPUCTF 2021 新生赛]sql

NSS [SWPUCTF 2021 新生赛]sql 很明显是sql&#xff0c;有waf。 参数是wllm get型传参&#xff0c;有回显&#xff0c;单引号闭合&#xff0c;回显位3 跑个fuzz看看waf 过滤了空格 and 报错注入 空格->%09 ->like and->&&爆库&#xff1a;test_db -1%27uni…

网络扫描与网络监听

前言&#xff1a;前文给大家介绍了网络安全相关方面的基础知识体系&#xff0c;以及什么是黑客&#xff0c;本篇文章笔者就给大家带来“黑客攻击五部曲”中的网络扫描和网络监听 目录 黑客攻击五部曲 网络扫描 按扫描策略分类 按照扫描方式分类 被动式策略 系统用户扫描 …

JS防抖与节流(含实例各二种写法 介绍原理)

防抖 防抖是什么&#xff1f; 单位时间内&#xff0c;频繁触发事件&#xff0c;只执行最后一次 通俗易懂点就是把防抖想象成MOBA游戏的回城&#xff0c;在回城过程中被打断就要重来 例子&#xff1a;我们来做一个效果&#xff0c;我们鼠标在盒子上移动&#xff0c;数字就变化 …

CVE-2021-41773/42013 apache路径穿越漏洞

影响范围 CVE-2021-41773 Apache HTTP server 2.4.49 CVE-2021-42013 Apache HTTP server 2.4.49/2.4.50 漏洞原理 Apache HTTP Server 2.4.49版本使用的ap_normalize_path函数在对路径参数进行规范化时会先进行url解码&#xff0c;然后判断是否存在…/的路径穿越符&#xf…

CMMI/ASPICE认证咨询及工具服务

服务概述 质量专家戴明博士的名言“如果你不能描述做事情的过程&#xff0c;那么你不知道你在做什么”。过程是连接有能力的工程师和先进技术的纽带&#xff0c;因此产品开发过程直接决定了产品的质量和研发的效率。 经纬恒润可结合多体系要求&#xff0c;如IATF16949\ISO26262…

Java 基础面试题,JVM 内存模型?

我们在 Java 岗位的面试题中&#xff0c;大概率会碰到这样一个面试题&#xff1a;请你解释你对 JVM 内存模型的理解。 今天我们就来回答一下这个问题&#xff1a; JDK 11 中的 JVM 内存模型可以分为以下几个部分&#xff1a; 程序计数器&#xff08;Program Counter&#xff…