【运筹优化】最短路算法之A星算法 + Java代码实现

news2025/2/1 9:14:39

文章目录

  • 一、A星算法简介
  • 二、A星算法思想
  • 三、A星算法 java代码
  • 四、测试


一、A星算法简介

A*算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快。
在这里插入图片描述


二、A星算法思想

A星(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是许多其他问题的常用启发式算法。注意——是最有效的直接搜索算法,之后涌现了很多预处理算法(如CH),在线查询效率是A*算法的数千甚至上万倍。

A*算法通过下面这个函数来计算每个节点的优先级, f ( n ) f(n) f(n) 越小,状态 n n n 被选择的优先级就越大:

公式表示为: f ( n ) = g ( n ) + h ′ ( n ) f(n)=g(n)+h'(n) f(n)=g(n)+h(n),

  • f ( n ) f(n) f(n) 是从初始状态经由状态 n n n 到目标状态的最小代价估计,
  • g ( n ) g(n) g(n) 是在状态空间中从初始状态到状态 n n n 的最小代价,
  • h ′ ( n ) h'(n) h(n) 是从状态 n n n 到目标状态的路径的最小估计代价。(对于路径搜索问题,状态就是图中的节点,代价就是距离)

假设 h ( n ) h(n) h(n) 为状态 n n n 到目标状态的路径的最小真实代价。

则保证找到最短路径(最优解的)条件,关键在于估价函数 f ( n ) f(n) f(n) 的选取(或者说 h ′ ( n ) h'(n) h(n) 的选取)。

h ′ ( n ) h'(n) h(n) 表达状态 n n n 到目标状态估计的距离,那么 h ′ ( n ) h'(n) h(n) 的选取大致有如下三种情况:

  • 如果 h ′ ( n ) < h ( n ) h'(n)< h(n) h(n)<h(n) ,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。
  • 如果 h ′ ( n ) = h ( n ) h'(n)=h(n) h(n)=h(n) ,此时的搜索效率是最高的。
  • 如果 h ′ ( n ) > h ( n ) h'(n)>h(n) h(n)>h(n) ,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

三、A星算法 java代码

@Data
public class AStar {
    // 0是路 1是墙 2是起点 3是终点
    private int[][] map;
    // 起点坐标
    int startI;
    int startJ;
    // 终点坐标
    int endI;
    int endJ;

    public AStar(int[][] map) {
        this.map = map;
        // 获取起点和终点坐标
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                if(map[i][j]==2){
                    startI = i;
                    startJ = j;
                }
                if(map[i][j]==3){
                    endI = i;
                    endJ = j;
                }
            }
        }
    }

    public void solve(){
        boolean[][] active = new boolean[map.length][map[0].length];
        PriorityBlockingQueue<Node> priorityBlockingQueue = new PriorityBlockingQueue<>();
        // 从起点出发
        ArrayList<int[]> initPath = new ArrayList<>();
        initPath.add(new int[]{startI,startJ});
        priorityBlockingQueue.add(new Node(startI,startJ,initPath,caculateDistance(startI,startJ)));
        active[startJ][startJ] = true;
        // 开始循环
        while (!priorityBlockingQueue.isEmpty()){
            Node node = priorityBlockingQueue.poll();
            if(node.getI()==endI && node.getJ()==endJ){
                for (int[] p : node.getPath()) {
                    System.out.println(Arrays.toString(p));
                }
                System.out.println("最短路长度为:"+node.getPath().size());
                break;
            }
            // 向四周进行扩充
            // 上
            int i1 = node.getI()-1;
            int j1 = node.getJ();
            if(isAble(i1,j1,active)){
                ArrayList<int[]> path = new ArrayList<>(node.getPath());
                path.add(new int[]{i1,j1});
                priorityBlockingQueue.add(new Node(i1,j1,path,caculateDistance(i1,j1)));
                active[i1][j1] = true;
            }
            // 下
            int i2 = node.getI()+1;
            int j2 = node.getJ();
            if(isAble(i2,j2,active)){
                ArrayList<int[]> path = new ArrayList<>(node.getPath());
                path.add(new int[]{i2,j2});
                priorityBlockingQueue.add(new Node(i2,j2,path,caculateDistance(i2,j2)));
                active[i2][j2] = true;
            }
            // 左
            int i3 = node.getI();
            int j3 = node.getJ()-1;
            if(isAble(i3,j3,active)){
                ArrayList<int[]> path = new ArrayList<>(node.getPath());
                path.add(new int[]{i3,j3});
                priorityBlockingQueue.add(new Node(i3,j3,path,caculateDistance(i3,j3)));
                active[i3][j3] = true;
            }
            // 右
            int i4 = node.getI();
            int j4 = node.getJ()+1;
            if(isAble(i4,j4,active)){
                ArrayList<int[]> path = new ArrayList<>(node.getPath());
                path.add(new int[]{i4,j4});
                priorityBlockingQueue.add(new Node(i4,j4,path,caculateDistance(i4,j4)));
                active[i4][j4] = true;
            }
        }
    }
    // 判断坐标是否可行
    private boolean isAble(int i,int j,boolean[][] active){
        if(i<0 || i>=map.length){
            return false;
        }
        if(j<0 || j>= map[0].length){
            return false;
        }
        if(map[i][j]==1 || active[i][j]){
            return false;
        }
        return true;
    }
    // 计算距离终点的曼哈顿
    private int caculateDistance(int i,int j){
        return Math.abs(i-endI)+Math.abs(j-endJ);
    }
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Node implements Comparable<Node>{
        int i;
        int j;
        List<int[]> path;
        // 距离终点的曼哈顿距离
        int lenToEnd;
        @Override
        public int compareTo(Node o) {
            return Integer.compare(lenToEnd+path.size(),o.lenToEnd+o.path.size());
        }

        @Override
        public String toString() {
            return "Node{" +
                    "i=" + i +
                    ", j=" + j +
                    ", lenToEnd=" + lenToEnd +
                    '}';
        }
    }
}

四、测试

public class Test {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        int[][] map = new int[][]{
                {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0},
                {0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0},
                {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0},
                {0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
                {0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0},
                {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
                {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
                {0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0},
                {0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
                {0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
                {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
                {0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0},
                {0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0},
                {0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0},
                {0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0},
                {0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1},
                {0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1},
                {0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1},
                {0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0},
        };
        new AStar(map).solve();
        System.out.println("用时:"+(System.currentTimeMillis()-start)+"ms");
    }
}

控制台输出:

[1, 4]
[1, 5]
[1, 6]
[1, 7]
[1, 8]
[1, 9]
[2, 9]
[2, 10]
[2, 11]
[3, 11]
[4, 11]
[5, 11]
[6, 11]
[7, 11]
[8, 11]
[9, 11]
[10, 11]
[10, 12]
[11, 12]
[12, 12]
[12, 11]
[13, 11]
[14, 11]
[15, 11]
[16, 11]
[17, 11]
[17, 12]
[17, 13]
[17, 14]
[18, 14]
[19, 14]
[19, 13]
[19, 12]
最短路长度为:33
用时:6ms

上面输出的例如:
[1, 4]
[1, 5]
[1, 6]
的文字代表最短路径(从上往下看):
即从(1,4)点走到(1,5)点,再从(1,5)点走到(1,6)点

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

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

相关文章

day52_Spring

今日内容 零、 复习昨日 一、Spring 零、 复习昨日 一、引言 以前 public class HelleServlet extends HttpServlet{UserService service new UsrServiceImpl();void doGet(){service.findUser();} }public interface UserService{User findUser(); } public class UserServ…

Tigase-Server 8.3.0在windows11下安装

一、JDK安装&#xff1a; tigase-server要求JDK 17,请先下载JDK17, 下载地址&#xff1a;https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe 配置环境变量&#xff1a;JAVA_HOME{JDK安装目录} 二、数据库安装&#xff1a;tigase-server8.3在windows下…

【算法系列 | 4】深入解析排序算法之——归并排序

序言 你只管努力&#xff0c;其他交给时间&#xff0c;时间会证明一切。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记一级论点蓝色&#xff1a;用来标记二级论点 决定开一个算法专栏&#xff0c;希望能帮助大…

Chrome内核插件开发报错:Unchecked runtime.lastError:的原因及解决办法。

本篇文章主要讲解,chrome内核插件开发时报错:Unchecked runtime.lastError: Extensions using event pages or Service Workers must pass an id parameter to chrome.contextMenus.create 的原因及解决办法。 日期:2023年6月10日 作者:任聪聪 报错现象: 查看报错路径,在…

项目经理必备!这四个高效管理工具帮你实现项目管理目标

在项目管理中&#xff0c;图形工具可以帮助我们让项目信息可视化&#xff0c;让项目管理更加高效&#xff0c;对于项目经理而言&#xff0c;这些工具都是好帮手。让我们一起看看&#xff0c;项目经理常用的管理工具都有那些吧~ 1&#xff0c;甘特图 甘特图是计划和管理项目的好…

【Spring使用注解更简单的实现Bean对象的存取】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、前言&#xff1a; 二、储存Bean对象和使…

天黑的时候如果下雨了,会比平常更亮一些

目录 一、最近的感受 二、自我的审视 三、如何变得强大 1.保持善良 2.不过度追求公平 3.在痛苦中找到自己的意义 4.令人振奋的生命力 四、情绪调节中的个人见解及如何处理情绪后的学习 1.运动 2.散步 3.找好朋友倾诉 五、总结 一、最近的感受 天黑的时候如果下雨了…

设计模式(十一):结构型之组合模式

设计模式系列文章 设计模式(一)&#xff1a;创建型之单例模式 设计模式(二、三)&#xff1a;创建型之工厂方法和抽象工厂模式 设计模式(四)&#xff1a;创建型之原型模式 设计模式(五)&#xff1a;创建型之建造者模式 设计模式(六)&#xff1a;结构型之代理模式 设计模式…

C语言:写一个代码,使用 试除法 打印100~200之间的素数(质数)

题目&#xff1a; 使用 试除法 打印100~200之间的素数。 素数&#xff08;质数&#xff09;&#xff1a;一个数只能被写成一和本身的积。 如&#xff1a;7只能写成1*7&#xff0c;那就是素数&#xff08;质数&#xff09;了。 思路一&#xff1a;使用试除法 总体思路&#xff…

HTML5 介绍

目录 1. HTML5介绍 1.1 介绍 1.2 内容 1.3 浏览器支持情况 2. 创建HTML5页面 2.1 <!DOCTYPE> 文档类型声明 2.2 <html>标签 2.3 <meta>标签 设置字符编码 2.4 引用样式表 2.5 引用JavaScript文件 3. 完整页面示例 4. 资料网站 1. HTML5介绍 1.1 介绍 …

带你手撕一颗红黑树

红黑树&#xff08;C&#xff09; 红黑树简述红黑树的概念红黑树的性质红黑树结点定义 一&#xff0c;红黑树的插入插入调整插入代码 二&#xff0c;红黑树的验证三&#xff0c;红黑树的删除待删除的结点只有一个子树删除结点颜色为红色删除结点颜色为黑色 删除的结点为叶子节点…

直流稳压电源与信号产生电路(模电速成)

目录 一、直流稳压电源 1、直流稳压电路 2、串联型稳压电路 3、集成稳压电路 二、信号产生电路 1、振荡电路 2、波形发生器 一、直流稳压电源 1、直流稳压电路 直流电源由 变压器、整流、滤波、稳压 四部分组成 整流&#xff1a;将交流变为直流 滤波&#xff1a;减小…

AI人工智能之科研论文搜索集锦

AI人工智能之科研论文搜索集锦 前言1. Google学术搜索2. Google搜索3. Arxiv#Example&#xff1a; 4. Github#Example&#xff1a; 5. Paperwithcode6. Connectedpapers7. OpenReview 总结 前言 如今越来越多领域都会与计算机、人工智能方面进行跨领域融合&#xff0c;一个万物…

帮忙投票的链接怎么弄的微信怎么创建投票链接设置投票

近些年来&#xff0c;第三方的微信投票制作平台如雨后春笋般络绎不绝。随着手机的互联网的发展及微信开放平台各项基于手机能力的开放&#xff0c;更多人选择微信投票小程序平台&#xff0c;因为它有非常大的优势。 1.它比起微信公众号自带的投票系统、传统的H5投票系统有可以图…

EMC学习笔记(二)模块划分及特殊器件的布局

模块划分及特殊器件的布局 1.模块划分1.1 按功能划分1.2 按频率划分1.3 按信号类型划分1.4 综合布局 2.特殊器件的布局2.1 电源部分2.2 时钟部分2.3 电感线圈2.4 总线驱动部分2.5 滤波器件 谈PCB的EMC设计,不能不谈PCB的模块划分及关键器件的布局。这一方面是某些频率发生器件、…

day51_mybatis

今日内容 零、 复习昨日 一、缓存 二、单例设计模式 零、 复习昨日 多表联查的时候 扩展类写接口设计方法写sql语句 不能直接映射成实体类resultMap 一对一 axxxxxxx一对多 collection 一、$和#的区别 使用# 使用$ 总结: #{} 相当于是预处理语句,会将#换成占位符?,字符串等…

【c语言进阶】深入挖掘数据在内存中的存储

深入挖掘数据在内存中的存储 数据类型介绍数据类型基本分类及其大小 整形在内存中的存储方式原码、反码、补码大小端介绍判断一个系统是大端还是小端 char与unsigned char值范围与图解整形存储相关练习题 浮点数在内存中的存储方式浮点数存储规则案列 结语 铁汁们&#xff0c;今…

计算机网络填空题

我会写下自己的答案和理解 希望自己可用在学习中体会到快乐&#xff0c;而不是麻木。 1. 网络协议三要素中语义是指 需要发出何种控制信息&#xff0c;完成何种动作以及做出何种响应 1.在计算机网络中要做到有条不紊的交换数据&#xff0c;就必须遵守一些事…

算法刷题-链表-移除链表元素

链表操作中&#xff0c;可以使用原链表来直接进行删除操作&#xff0c;也可以设置一个虚拟头结点再进行删除操作&#xff0c;接下来看一看哪种方式更方便。 203.移除链表元素 力扣题目链接 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&…

红黑树(Red Black Tree)基本性质 + 建树

定义 红黑树&#xff1a;一种特殊的二叉搜索树 二叉搜索树&#xff1a;一种树的类型&#xff0c;每个节点最多有两个子节点&#xff0c;其中其左节点一定小于当前节点&#xff0c;右节点一定大于当前节点 二叉树的缺点&#xff1a;如果给定的初始序列顺序不好&#xff0c;可能…