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

文章目录

  • 一、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.mfbz.cn/a/27498.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

javaScript蓝桥杯-----天气趋势 A

目录 一、介绍二、准备三、目标四、代码五、完成 一、介绍 日常生活中&#xff0c;气象数据对于人们的生活具有非常重要的意义&#xff0c;数据的表现形式多种多样&#xff0c;使用图表进行展示使数据在呈现上更加直观。 本题请实现一个 Y 城 2022 年的天气趋势图。 二、准备…

100天精通Python(可视化篇)——第88天:全网最全Seaborn库常用绘图3万字总结(参数说明+案例实战)

文章目录 一、Seaborn介绍1.1 介绍1.2 安装1.3 风格设置1.3.1 style&#xff08;风格&#xff09;1.3.2 context&#xff08;环境设置&#xff09; 1.4 调色盘设置1.5 数据集下载 二、Relational plots&#xff08;关系图&#xff09;2.1 scatterplot&#xff08;散点图&#x…

SpringSecurity 总结

SpringSecurity 总结 第一章 权限管理 权限管理SpringSecurity 简介整体架构 权限管理&#xff1a; 实现: "对用户访问系统的控制"(身份认证) &#xff0c; 按照 "安全规则"或者 "安全策略" (对已经认证的用户进行授权) 控制&#xff0c;用…

K8s in Action 阅读笔记——【13】Securing cluster nodes and the network

K8s in Action 阅读笔记——【13】Securing cluster nodes and the network 13.1 Using the host node’s namespaces in a pod Pod中的容器通常在不同的Linux名称空间下运行&#xff0c;这使得它们的进程与其他容器或节点默认名称空间下运行的进程隔离开来。 例如&#xff…

【计算机组成与体系结构Ⅰ】课程设计——基于Logisim的模型计算机设计

基于Logisim的模型计算机设计 一、实验目的 基于Logisim软件&#xff0c;根据一个模型指令系统&#xff0c;在逐步学习和了解计算机组成各部分逻辑组成和各部分互联的基础上&#xff0c;深入理解课程中的知识点&#xff0c;利用此软件设计并实现一个模拟的8位模型计算机原型。…

Python爬取影评并进行情感分析和数据可视化

Python爬取影评并进行情感分析和数据可视化 文章目录 Python爬取影评并进行情感分析和数据可视化一、引言二、使用requestsBeautifulSoup进行影评的爬取1、分析界面元素2、编写代码 三、情感分析1、数据预处理2、情感分析3、数据可视化 一、引言 前几天出了《航海王&#xff1…

delete 清空表之后,磁盘空间未发生变化?

上篇文章结尾和小伙伴们留了一个小问题&#xff0c;就是关于 optimize table 命令&#xff0c;今天我想花点时间再来和小伙伴们聊一聊这个话题。 1. 删除空洞 1.1 案例展示 首先我们先来看这样一个例子。 我现在有一个名为 sakila 的数据库&#xff0c;该库中有一个 film 表…

x宝评论抓取

#某宝评论接口sign参数逆向 1.接口速览 多次请求发现&#xff0c;t为时间戳&#xff0c;sign为加密参数&#xff0c;盲猜和data、t有关&#xff0c;sign为32位&#xff0c;盲猜是字符串的32位的MD5 2.搜索js代码 这里为搜索的是appKey&#xff0c;就找到了sign&#xff0c;然…

【CSS】常见的选择器

1.标签选择器 语法 标签 { }作用 标签选择器用于选择某种标签比如 选择p标签&#xff0c;并设置背景颜色 p { background-color:yellow; }例子 选择div标签&#xff0c;并将其字体大小设置为100px&#xff0c;字体设置为"微软雅黑"&#xff0c;文字颜色设置为r…

UDP协议和TCP协议

目录 UDP TCP 通过序列号与确认应答提高可靠性 为什么TCP是三次握手 为什么是四次挥手 超时重传机制 流控制 利用窗口控制提高速度 窗口控制与重发控制 拥塞控制 延迟确认应答 捎带应答 UDP UDP是不具有可靠性的数据报协议。细微的处理它会交给上层的应用去完成。…

从零开始,5分钟轻松实现Spring Boot与RabbitMQ的无缝集成

&#x1f30f; 环境 docker v4.16.2springboot 2.7.0RabbitMQ 3.9.1 rabbitmq_delayed_message_exchange 3.9.0 ps&#xff1a;代码地址 gitee &#x1fa9c; 服务架构 使用maven多模块&#xff0c;将生产者、消费者分别以springboot项目启动&#xff0c;两者通过RabbitMQ…

面试总结个人版

一、面试题 java 集合 &#xff0c; spring springmvc springboot springcloud 数据库相关的&#xff0c; redis 相关 &#xff0c;mq 相关 &#xff0c;结合业务的场景题 1、part one 集合 HashMap底层原理 HashMap是基于哈希表的Map接口的非同步实现。元素以键值对的形式存…

AI-Prompt 1.0 版简介公测!你的AI提示词网站!

提示词&#xff08;Prompt&#xff09; 是什么&#xff1f; 在 AI 大模型中&#xff0c;一个 prompt 是一个输入文本&#xff0c;用于触发模型生成输出。例如&#xff0c;当我们向一个 AI 大模型提交需求时&#xff0c;我们的需求就是一个 prompt。 在介绍产品之前&#xff0c;…

CoreDX DDS应用开发指南(4)DDS实体h和主题

6 DDS实体 DDS标准定义了一个体系结构,该体系结构表示构成DDS API实体的面向对象模型。这些实体充当中间件和应用软件之间的接口。为了开发支持DDS的应用程序,开发人员必须创建、交互并销毁这些DDS实体。 本章概述了DDS实体和相关概念。 6.1 DDS实体层次结构 构成DDS API的主…

OpenELB 在 CVTE 的最佳实践

作者&#xff1a;大飞哥&#xff0c;视源电子股份运维工程师&#xff0c; KubeSphere 社区用户委员会广州站站长&#xff0c;KubeSphere Ambassador。 公司介绍 广州视源电子科技股份有限公司&#xff08;以下简称视源股份&#xff09;成立于 2005 年 12 月&#xff0c;旗下拥…

[7]PCB设计实验|认识常用元器件|电容器|19:00~19:30

目录 一、电容器的识别 电容的应用 1. 电容有通交流阻隔直流电的作用 2. 有滤波、耦合、旁路作用等 3. 有些电容是有极性&#xff0c;有些是没有极性 二、常见电容器 1. 贴片电容 a、材质瓷片 b、材质钽介质 c、材质电解质 2. 手插电容 a、瓷片电容 b、聚脂电容 …

Windows命令行查找并kill进程及常用批处理命令汇总

Windows命令行查找并kill进程及常用命令汇总 打开命令窗口 开始—->运行—->cmd&#xff0c;或者是 windowR 组合键&#xff0c;调出命令窗口。 cmd命令行杀死Windows进程方法 1、根据进程名称批量kill 1&#xff09;、执行tasklist|more检索进程 2&#xff09;、执…

使用OpenAI创建对话式聊天机器人

引言 在当今的技术世界中&#xff0c;人工智能&#xff08;AI&#xff09;的发展迅猛&#xff0c;为我们带来了许多令人兴奋的创新。其中&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域的进展使得开发对话式聊天机器人成为可能。OpenAI是一家领先的人工智能研究实验…

常见的JS存储方式及其特点

在前端开发中&#xff0c;经常需要在浏览器端存储和管理数据。为了实现数据的持久化存储和方便的访问&#xff0c;JavaScript提供了多种数据存储方式。本文将介绍几种常见的前端JS数据存储方式及其特点。 1. Cookie Cookie是一种小型的文本文件&#xff0c;由浏览器保存在用户…

如何利用google的protobuf设计、实现自己的RPC框架

一、前言 这篇文章我们就来聊一聊 RPC 的相关内容&#xff0c;来看一下如何利用 Google 的开源序列化工具 protobuf&#xff0c;来实现一个我们自己的 RPC 框架&#xff0c;内容有点长&#xff0c;请耐心看完。 序列化[1]&#xff1a;将结构数据或对象转换成能够被存储和传输&…
最新文章