代码随想录打卡|Day53 图论(Floyd 算法精讲 、A * 算法精讲 (A star算法)、最短路算法总结篇、图论总结 )

news2025/6/2 8:40:44

图论part11

Floyd 算法精讲

代码随想录链接
题目链接

在这里插入图片描述

代码

三维DP数组
import java.util.Scanner;

public class Main {
    // 定义最大距离值,避免使用Integer.MAX_VALUE防止加法溢出
    public static final int INF = 100000000; // 10^8足够大且不会溢出

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        /* 
         * 1. 输入处理
         * 第一行:N(景点数量), M(道路数量)
         * 接下来M行:u, v, w (双向道路)
         * 然后一行:Q(查询数量)
         * 接下来Q行:start, end (查询起点和终点)
         */
        int n = sc.nextInt(); // 景点数量 (1到n编号)
        int m = sc.nextInt(); // 道路数量
        
        /*
         * 2. 初始化三维DP数组
         * dp[k][i][j]表示从i到j,允许经过前k个节点(1..k)的最短路径
         * 这里k的范围是0到n:
         * - k=0表示不允许经过任何中间节点(直接边)
         * - k=n表示允许经过所有节点
         */
        int[][][] dp = new int[n+1][n+1][n+1];
        
        // 初始化所有距离为INF,自己到自己的距离为0
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                for (int k = 0; k <= n; k++) {
                    if (i == j) {
                        dp[k][i][j] = 0; // 自己到自己的距离为0
                    } else {
                        dp[k][i][j] = INF; // 初始化为最大值
                    }
                }
            }
        }
        
        // 3. 读取道路信息并填充初始距离(k=0的情况)
        for (int i = 0; i < m; i++) {
            int u = sc.nextInt();
            int v = sc.nextInt();
            int w = sc.nextInt();
            // 双向道路,两个方向都要设置
            dp[0][u][v] = w;
            dp[0][v][u] = w;
        }
        
        /* 
         * 4. Floyd-Warshall算法核心部分(三维DP版本)
         * 状态转移方程:
         * dp[k][i][j] = min(dp[k-1][i][j], dp[k-1][i][k] + dp[k-1][k][j])
         * 含义:
         * - 从i到j允许经过前k个节点的最短路径 =
         *   min(不经过k的最短路径, 经过k的最短路径)
         */
        for (int k = 1; k <= n; k++) {         // 中间节点
            for (int i = 1; i <= n; i++) {     // 起点
                for (int j = 1; j <= n; j++) { // 终点
                    // 比较两种情况:
                    // 1. 不经过节点k的最短路径(dp[k-1][i][j])
                    // 2. 经过节点k的最短路径(dp[k-1][i][k] + dp[k-1][k][j])
                    dp[k][i][j] = Math.min(dp[k-1][i][j], dp[k-1][i][k] + dp[k-1][k][j]);
                }
            }
        }
        
        // 5. 处理查询
        int q = sc.nextInt(); // 查询数量
        for (int i = 0; i < q; i++) {
            int start = sc.nextInt();
            int end = sc.nextInt();
            // 使用允许经过所有节点(n个)的最短路径作为结果
            // 如果不可达则输出-1
            System.out.println(dp[n][start][end] == INF ? -1 : dp[n][start][end]);
        }
    }
}
二维DP数组
import java.util.Scanner;

public class Main {
    // 定义最大距离值,避免使用Integer.MAX_VALUE防止加法溢出
    public static final int INF = 100000000; // 10^8足够大且不会溢出

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        // 1. 读取景点数量和道路数量
        int n = sc.nextInt(); // 景点数量 (1到n编号)
        int m = sc.nextInt(); // 道路数量
        
        // 2. 初始化距离矩阵
        int[][] dist = new int[n+1][n+1]; // 1-based索引
        
        // 初始化所有距离为INF,自己到自己的距离为0
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i == j) {
                    dist[i][j] = 0;
                } else {
                    dist[i][j] = INF;
                }
            }
        }
        
        // 3. 读取道路信息并填充初始距离
        for (int i = 0; i < m; i++) {
            int u = sc.nextInt();
            int v = sc.nextInt();
            int w = sc.nextInt();
            // 双向道路,两个方向都要设置
            dist[u][v] = w;
            dist[v][u] = w;
        }
        
        // 4. Floyd-Warshall算法核心部分
        for (int k = 1; k <= n; k++) {         // 中间节点
            for (int i = 1; i <= n; i++) {     // 起点
                for (int j = 1; j <= n; j++) { // 终点
                    // 如果通过中间节点k可以缩短i到j的距离
                    if (dist[i][k] + dist[k][j] < dist[i][j]) {
                        dist[i][j] = dist[i][k] + dist[k][j];
                    }
                }
            }
        }
        
        // 5. 处理查询
        int q = sc.nextInt(); // 查询数量
        for (int i = 0; i < q; i++) {
            int start = sc.nextInt();
            int end = sc.nextInt();
            // 输出结果,如果不可达则输出-1
            System.out.println(dist[start][end] == INF ? -1 : dist[start][end]);
        }
    }
}

A * 算法精讲 (A star算法)

代码随想录链接
题目链接

在这里插入图片描述

代码(超时,示例正确)

import java.util.*;

public class Main {
    
    // 定义骑士的8种可能移动方式(马走日)
    private static final int[][] MOVES = {
        {1, 2}, {2, 1}, {2, -1}, {1, -2},
        {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}
    };
    
    // 节点类,表示棋盘上的一个位置
    static class Node implements Comparable<Node> {
        int x, y;        // 当前位置坐标
        int g;           // 从起点到当前节点的实际代价
        int h;           // 到目标节点的启发式估计代价
        Node parent;      // 父节点(用于路径回溯)
        
        public Node(int x, int y) {
            this.x = x;
            this.y = y;
            this.g = 0;
            this.h = 0;
        }
        
        // 计算总代价f = g + h
        public int f() {
            return g + h;
        }
        
        // 用于优先队列排序
        @Override
        public int compareTo(Node other) {
            return Integer.compare(this.f(), other.f());
        }
        
        // 重写equals和hashCode用于比较节点
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            Node node = (Node) obj;
            return x == node.x && y == node.y;
        }
        
        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }
    
    // A*算法实现
    public static int aStarKnightPath(int startX, int startY, int targetX, int targetY) {
        // 如果起点就是终点,直接返回0
        if (startX == targetX && startY == targetY) {
            return 0;
        }
        
        // 边界检查
        if (!isValid(startX, startY) || !isValid(targetX, targetY)) {
            return -1;
        }
        
        // 初始化开放列表和关闭列表
        PriorityQueue<Node> openList = new PriorityQueue<>();
        Set<Node> closedList = new HashSet<>();
        
        // 创建起点节点
        Node startNode = new Node(startX, startY);
        startNode.g = 0;
        startNode.h = heuristic(startX, startY, targetX, targetY);
        openList.add(startNode);
        
        while (!openList.isEmpty()) {
            // 获取当前最优节点
            Node currentNode = openList.poll();
            
            // 如果到达目标节点,返回步数
            if (currentNode.x == targetX && currentNode.y == targetY) {
                return currentNode.g;
            }
            
            // 将当前节点加入关闭列表
            closedList.add(currentNode);
            
            // 遍历所有可能的移动
            for (int[] move : MOVES) {
                int newX = currentNode.x + move[0];
                int newY = currentNode.y + move[1];
                
                // 检查新位置是否有效
                if (!isValid(newX, newY)) {
                    continue;
                }
                
                // 创建新节点
                Node neighbor = new Node(newX, newY);
                neighbor.g = currentNode.g + 1;  // 每步代价为1
                neighbor.h = heuristic(newX, newY, targetX, targetY);
                neighbor.parent = currentNode;
                
                // 如果已经在关闭列表中,跳过
                if (closedList.contains(neighbor)) {
                    continue;
                }
                
                // 检查是否在开放列表中
                boolean inOpenList = false;
                for (Node node : openList) {
                    if (node.equals(neighbor)) {
                        inOpenList = true;
                        // 如果找到更优路径,更新节点
                        if (neighbor.g < node.g) {
                            node.g = neighbor.g;
                            node.parent = currentNode;
                        }
                        break;
                    }
                }
                
                // 如果不在开放列表中,加入
                if (!inOpenList) {
                    openList.add(neighbor);
                }
            }
        }
        
        // 如果开放列表为空且未找到路径,返回-1
        return -1;
    }
    
    // 启发式函数:曼哈顿距离除以3(骑士每步最多移动3格)
    private static int heuristic(int x1, int y1, int x2, int y2) {
        return (Math.abs(x1 - x2) + Math.abs(y1 - y2)) / 3;
    }
    
    // 检查坐标是否有效
    private static boolean isValid(int x, int y) {
        return x >= 1 && x <= 1000 && y >= 1 && y <= 1000;
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        for (int i = 0; i < n; i++) {
            int a1 = sc.nextInt();
            int a2 = sc.nextInt();
            int b1 = sc.nextInt();
            int b2 = sc.nextInt();
            
            int steps = aStarKnightPath(a1, a2, b1, b2);
            System.out.println(steps);
        }
    }
}

最短路算法总结篇

代码随想录链接


图论总结篇

代码随想录链接


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

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

相关文章

yum安装nginx后无法通过服务方式启动

背景 在linux系统下&#xff0c;通过yum方式安装nginx后 通过nginx命令 nginx 可以启动nginx 但是作为测试或者生产服务器&#xff0c;我们需要配置开机自启动&#xff0c;这时候需要用服务方式启动 yum安装后的nginx 已经默认生成了服务启动方式的 nginx.service文件 按…

数据基座觉醒!大数据+AI如何重构企业智能决策金字塔(下)

1. 数据架构的量子跃迁 1.1 从线性堆叠到立体网络 传统六层架构正在经历基因重组。某智能家居企业将数据流转路径重构为三维拓扑网络后&#xff0c;新品研发周期从18个月压缩至9个月。这个改造的核心在于打破数据层间的物理隔离&#xff0c;让原始数据流能直接触达决策中枢。…

在线博客系统【测试报告】

&#x1f552; 一. 项目背景 由于纸质笔记容易丢失&#xff0c;携带不变&#xff0c;为了方便自己学习的过程中记录笔记&#xff0c;特开发了这个博客系统。这个系统后端采用 SpringBoot MyBatis SpringMVC &#xff1b;前端使用Html CSS JS&#xff1b;数据库使用的是Mysq…

Void:免费且隐私友好的 AI 编码利器,挑战 Cursor 地位?

开发者圈儿里最近有点小激动&#xff0c;大家都在议论一个叫Void的开源AI代码编辑器。这家伙在GitHub上人气飙涨&#xff0c;短时间内就斩获了超过22.1k的星标&#xff0c;简直成了科技圈的新宠。它被誉为“黑马”&#xff0c;不仅因为它继承了大家都很熟悉的Visual Studio Cod…

Elasticsearch的写入流程介绍

Elasticsearch 的写入流程是一个涉及 分布式协调、分片路由、数据同步和副本更新 的复杂过程,其设计目标是确保数据一致性、可靠性和高性能。以下是写入流程的详细解析: 一、写入流程总览 二、详细步骤解析 1. 客户端请求路由 请求入口:客户端(如 Java 客户端、REST API)…

【PCB工艺】PCB设计中的基本概念

此文结合实例讲解PCB的设计流程和一些基本概念。 🧱 PCB 是什么? PCB(Printed Circuit Board)(即印制线路板) 是电子元器件的载体,是没有焊接任何器件的“裸板”。 PCB只是板子,没有焊接元件,而PCBA可以理解为焊接好元件的完成板子。 简单点说,PCB 只包含:铜线、电源…

WPF事件处理器+x名称空间

目录 ​编辑 一、事件处理器知识点 1. XAML中的事件绑定 2. C#中的事件处理方法 3. 方法签名解释 4. 命名规范 工作流程 二、导入引用名称空间 三、x名称空间及其常用元素 &#xff08;1&#xff09;x名称空间的由来和作用 &#xff08;2&#xff09;x名称空间里都有…

具身智能:OpenAI 的真正野心与未来展望

提到 ChatGPT&#xff0c;你对它的第一印象是什么&#xff1f;是担心它会威胁到工程师的工作&#xff0c;还是觉得它只是个会说空话的工具&#xff1f;或许你正在学习一些简单的教程&#xff0c;试图用它来建立知识库&#xff0c;自动化日常工作&#xff0c;觉得它不过如此&…

Lyra学习笔记2 GFA_AddComponents与ULyraPlayerSpawningManagerComponent

目录 前言GameFeatureAction_AddComponentsULyraPlayerSpawningManagerComponent缓存所有PlayerStart位置选择位置 前言 1.以control模式为例 2.比较散&#xff0c;想单独拿出一篇梳理下Experience的流程 GameFeatureAction_AddComponents 这部分建议看 《InsideUE5》GameFeatu…

个人健康中枢的多元化AI软件革新与精准健康路径探析

引言 人工智能技术的迅猛发展正在重塑医疗健康领域的服务模式和用户体验。随着多模态大模型、MCP协议、A2A协议和思考链算法等创新技术的出现,个人健康中枢正在经历一场深刻的软件革新。这些技术不仅打破了传统健康管理系统的信息孤岛,还通过多维度数据整合和深度推理能力,…

Matlab实现LSTM-SVM时间序列预测,作者:机器学习之心

Matlab实现LSTM-SVM时间序列预测&#xff0c;作者&#xff1a;机器学习之心 目录 Matlab实现LSTM-SVM时间序列预测&#xff0c;作者&#xff1a;机器学习之心效果一览基本介绍程序设计参考资料 效果一览 基本介绍 该代码实现了一个结合LSTM和SVM的混合模型&#xff0c;用于时间…

JAVA 集合的进阶 泛型的继承和通配符

1 泛型通配符 可以对传递的类型进行限定 1.1 格式 ? 表示不确定的类型 &#xff1f;extends E&#xff1a; 表示可以传递 E 或者 E 所有的子类类型 &#xff1f;super E&#xff1a; 表示可以传递 E 或者 E 所有的父类类…

下一代液晶显示底层技术与九天画芯的技术突围

一、液晶产业&#xff1a;撑起数字经济的显示脊梁 &#xff08;一&#xff09;全球显示市场的核心支柱 作为电子信息产业的战略基石&#xff0c;液晶显示&#xff08;LCD&#xff09;占据全球平板显示市场超 60% 的份额&#xff0c;2022 年全球市场规模达 782.41 亿元&#xf…

[NOIP 2001 普及组] 求先序排列 Java

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);String infixOrder sc.nextLine(); // 中序String postOrder sc.nextLine(); // 后序sc.close();System.out.println(preOrder(infixOrder, postOrder))…

Rockey Linux 安装ffmpeg

1.环境准备 Rockey linux 9.2 ffmpeg 静态资源包 这个是我自己的&#xff1a; https://download.csdn.net/download/liudongyang123/90920340https://download.csdn.net/download/liudongyang123/90920340 这个是官网的 Releases BtbN/FFmpeg-Builds GitHub 以上两个资…

STM32 Modbus RTU从机开发实战:核心实现与五大调试陷阱解析

知识点1【CRC校验】 CRC校验生成网址 CRC&#xff08;循环冗余校验&#xff09;在线计算_ip33.com 知识点2【代码演示】 代码书写思路 代码演示 main.c #include "stm32f10x.h" #include "stm32f10x_conf.h" #include "rs485.h"int main(voi…

Python----目标检测(《Fast R-CNN》和Fast R-CNN)

一、《Fast R-CNN》 1.1、基本信息 作者&#xff1a;Ross Girshick 机构&#xff1a;Microsoft Research 发表时间&#xff1a;2015年 论文链接&#xff1a;arXiv:1504.08083 代码开源&#xff1a;GitHub仓库&#xff08;MIT License&#xff09; 1.2、主要内容 Fast R…

iEKF的二维应用实例

如果熟悉 EKF 与卡尔曼的推导的话&#xff0c;iEKF 就比较容易理解&#xff0c;关于卡尔曼滤波的推导以及EKF&#xff0c;可以参考以前的文章&#xff1a; 卡尔曼滤波原理&#xff1a;https://blog.csdn.net/a_xiaoning/article/details/130564473?spm1001.2014.3001.5502 E…

【通关文件操作(下)】--文件的顺序读写(续),sprintf和sscanf函数,文件的随机读写,文件缓冲区,更新文件

目录 四.文件的顺序读写(续) 4.8--fwrite函数 4.9--fread函数 五.sprintf函数和sscanf函数 5.1--函数对比 5.2--sprintf函数 5.3--sscanf函数 六.文件的随机读写 6.1--fseek函数 6.2--ftell函数 6.3--rewind函数 七.文件缓冲区 7.1--fflush函数 八.更新文件 &…

mysql的Memory引擎的深入了解

目录 1、Memory引擎介绍 2、Memory内存结构 3、内存表的锁 4、持久化 5、优缺点 6、应用 前言 Memory 存储引擎 是 MySQL 中一种高性能但非持久化的存储方案&#xff0c;适合临时数据存储和缓存场景。其核心优势在于极快的读写速度&#xff0c;需注意数据丢失风险和内存占…