当前位置: 首页 > news >正文

最短路径问题

如图,设定源点为D,终点为A,则D到A的最短路径是多少?

 算法思路:

第一步,从源点D出发,此时能到达的选择是C和E,我们根据路径长度选择最少的作为下一个节点,于是选择C,

第二步,到达C后,标记C已经走过了,后续再做选择时,排除C。然后将所有C能到达的节点告知D,也就是B、F、E。由D来分辨,B、F、E这些点,是通过C节点路最短,还是D现有方案最短。选择最短的方案记录下来。然后选择B、F、E中C节点最近的、没标记过的节点作为下一步。

第三步,重复第二步操作,直到选不到下一个节点而结束。

考虑特殊的情况,假如图不是闭环的,这个方式可能会被引导在断路的地方停止。于是记录走过的路,当找不到路的时候,确认end没有找到,且还有节点没被标记的情况下,退回上一个路口。

(1)如果节点都被标记或者已经找到终点了,就退出

(2)如果还有节点未被标记可以回退上一次选择的地方继续选择。

最后直接询问源节点D中对于终点A的方案是什么,最短路径是多少。

代码:

封装图中的节点

   class Node {String name;//当前节点名称Map<String, Integer> path = new HashMap<>();//目标节点->最短路径public Node(String name) { this.name = name; }/*** 更新到达某个节点的最短路径* @param name 目标节点* @param len 最短路径*/public void update(String name, int len) {path.put(name, len);}/*** 获取指定节点的最短路径* @param name 目标节点* @return 最短路径*/public int getLen(String name) {return path.getOrDefault(name, Integer.MAX_VALUE);}}

用到全局变量存储信息,方法里传递这些也行,就是不好看

Map<String, Node> map = new HashMap<>();//节点对象map
Map<String, Boolean> sign = new HashMap<>();//节点标记
List<String> list = new ArrayList<>();//记录走的路径,处理碰到死路的情况,可以退上一个节点

初始化代码,将图上的数据跑入节点对象中。

Object[][] params = {{"A", "B", 12},{"A", "F", 16},{"A", "G", 14},{"B", "F", 7},{"B", "C", 10},{"C", "F", 6},{"C", "E", 5},{"C", "D", 3},{"D", "E", 4},{"E", "F", 2},{"E", "G", 8},{"F", "G", 9}
};
//导入路径数据
for(Object[] p:params){if(!map.containsKey((String)p[0]))map.put((String)p[0],new Node((String) p[0]));if(!map.containsKey((String)p[1]))map.put((String)p[1],new Node((String) p[1]));map.get((String)p[0]).update((String)p[1],(int)p[2]);map.get((String)p[1]).update((String)p[0],(int)p[2]);
}

开始算法

    /*** 选择它下面最小路径出发,更新自己到达最近节点位置** @param name*/boolean f(String name, Node start, String end) {Node now = map.get(name);//获取节点实体sign.put(name, true);//标记已经走过了list.add(name);/*** 更新源节点对能到达节点的最短路径,当前节点是源节点的时候不用更新*/if (!name.equals(start.name)) {int nowLen = start.getLen(name);//取出源节点到当前节点的最短路径,用于后续计算for (String key : now.path.keySet()) {//取出当前节点能直达的所有节点if (!key.equals(start.name)) {//将当前节点到达每一个节点的路径信息告知给到源节点,让源节点扩充自己的最短路径数据int newNodeLen = now.getLen(key) + nowLen;//源节点到新节点的路径长度if (start.getLen(key) > newNodeLen) { //源节点取出原有方案,对比,保留最短的方案start.update(key, newNodeLen);map.get(key).update(start.name, newNodeLen);//路径双方都更新}}}}String nextName = getNextName(now,end);if (nextName == null) return true;return f(nextName, start, end);}

里面涉及到选择最近节点的方法以及包含死路的时候回退操作,

    /*** 获取下一个路径节点* @param now* @param end* @return*/public static String getNextName(Node now,String end){String nextName = null;int min = Integer.MAX_VALUE;for (String key : now.path.keySet()) {if (sign.containsKey(key) && sign.get(key)) continue;if (now.getLen(key) < min) {min = now.getLen(key);nextName = key;}}if (nextName == null) {if (sign.containsKey(end) && sign.get(end)) return null;}else{return nextName;}list.remove(list.size()-1);return getNextName(map.get(list.get(list.size()-1)),end);}

最后使用上面这些东西

String start="D";//源节点
String end="A";//目标节点
f(start, map.get(start), end);
System.out.println(map.get(start).getLen(end));

无脑完整代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class Main {public static Map<String, Node> map = new HashMap<>();//节点信息public static Map<String, Boolean> sign = new HashMap<>();//防止重复计算public static List<String> list = new ArrayList<>();//记录走的路径,处理碰到死路的情况,可以退上一个节点public static void main(String[] args) {init();//初始化数据String start = "D";//源节点String end = "A";//目标节点f(start, map.get(start), end);//算法寻找System.out.println(map.get(start).getLen(end));//拿出来始终节点的最短路径}/*** 初始化数据*/public static void init(){Object[][] params = {{"A", "B", 12},{"A", "F", 16},{"A", "G", 14},{"B", "F", 7},{"B", "C", 10},{"C", "F", 6},{"C", "E", 5},{"C", "D", 3},{"D", "E", 4},{"E", "F", 2},{"E", "G", 8},{"F", "G", 9}};//导入路径数据for (Object[] p : params) {if (!map.containsKey((String) p[0])) map.put((String) p[0], new Node((String) p[0]));if (!map.containsKey((String) p[1])) map.put((String) p[1], new Node((String) p[1]));map.get((String) p[0]).update((String) p[1], (int) p[2]);map.get((String) p[1]).update((String) p[0], (int) p[2]);}}/*** 选择它下面最小路径出发,更新自己到达最近节点位置** @param name*/public static boolean f(String name, Node start, String end) {Node now = map.get(name);//获取节点实体sign.put(name, true);//标记已经走过了list.add(name);/*** 更新源节点对能到达节点的最短路径,当前节点是源节点的时候不用更新*/if (!name.equals(start.name)) {int nowLen = start.getLen(name);//取出源节点到当前节点的最短路径,用于后续计算for (String key : now.path.keySet()) {//取出当前节点能直达的所有节点if (!key.equals(start.name)) {//将当前节点到达每一个节点的路径信息告知给到源节点,让源节点扩充自己的最短路径数据int newNodeLen = now.getLen(key) + nowLen;//源节点到新节点的路径长度if (start.getLen(key) > newNodeLen) { //源节点取出原有方案,对比,保留最短的方案start.update(key, newNodeLen);map.get(key).update(start.name, newNodeLen);//路径双方都更新}}}}String nextName = getNextName(now,end);if (nextName == null) return true;return f(nextName, start, end);}/*** 获取下一个路径节点* @param now* @param end* @return*/public static String getNextName(Node now,String end){String nextName = null;int min = Integer.MAX_VALUE;for (String key : now.path.keySet()) {if (sign.containsKey(key) && sign.get(key)) continue;if (now.getLen(key) < min) {min = now.getLen(key);nextName = key;}}if (nextName == null) {if (sign.containsKey(end) && sign.get(end)) return null;}else{return nextName;}list.remove(list.size()-1);return getNextName(map.get(list.get(list.size()-1)),end);}
}
class Node {String name;//当前节点名称Map<String, Integer> path = new HashMap<>();//目标节点->最短路径public Node(String name) {this.name = name;}/*** 更新到达某个节点的最短路径** @param name 目标节点* @param len  最短路径*/public void update(String name, int len) {path.put(name, len);}/*** 获取指定节点的最短路径** @param name 目标节点* @return 最短路径*/public int getLen(String name) {return path.getOrDefault(name, Integer.MAX_VALUE);}
}

相关文章:

最短路径问题

如图&#xff0c;设定源点为D&#xff0c;终点为A&#xff0c;则D到A的最短路径是多少&#xff1f; 算法思路&#xff1a; 第一步&#xff0c;从源点D出发&#xff0c;此时能到达的选择是C和E&#xff0c;我们根据路径长度选择最少的作为下一个节点&#xff0c;于是选择C&…...

国内有哪些SAAS软件?SAAS软件有哪些优点?

国内有哪些SAAS软件&#xff1f;SAAS软件有哪些优点&#xff1f;不请自来答一下&#xff0c;通过SaaS软件与传统软件的对比来详细讲下SaaS软件有哪些优点&#xff1f; 配合以下内容食用更佳&#xff1a; 关于概念——深度详解什么是SaaS&#xff08;软件即服务&#xff09;关…...

分享两组不同的3D VR卡片

最近某音上出现了很多VR视频&#xff0c;转动手机可以看到手机界面未显示出来的场景。这种事情我觉得我们也可以做到。 所以两种不同的3D VR卡片来了&#xff1a; 第一种是横向或上下可以拖动极大的距离。卡片上的信息会随着拖动移动&#xff0c;但不会显示更多的信息&#x…...

外贸人如何精准开发客户?Facebook开发客户全攻略

现在做跨境的都了解的一个社媒平台就是Facebook了&#xff0c;因为很多人都会拿Facebook来开发客户&#xff0c;忙里偷闲&#xff0c;今天东哥就来聊聊用Facebook开发客户的一些心得。 用Facebook开发客户的心得 1、利用关键词搜索 使用行业相关的关键词、产品特定的关键词、相…...

一、Git安装(Git+TortoiseGit图形化)

Git 是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同&#xff0c;它采用了分布式版本库的方式…...

mysql死锁,如何产生?如何发现?如何处理?

1 产生死锁 就是资源互斥 例子如下 好的&#xff0c;请参考以下 SQL 语句来创建 base_account_item 表和向表中插入一些数据&#xff1a; CREATE TABLE base_account_item (id INT(11) NOT NULL,account_item_name VARCHAR(50) NOT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEF…...

YOLO V1-V3 简单介绍

目录 1. YOLO 2. YOLO V1 3. YOLO V2 4. YOLO V3 5. YOLO V3 SPP网络 5.1 Mosaic 图像增强 5.2 SPP 模块 5.3 CIou Loss 5.4 Focal loss 1. YOLO YOLO 是目标检测任务强大的算法&#xff0c;将目标检测的问题转换边界框和相关概率的回归问题&#xff0c;是目标检测…...

数据结构总结1:了解数据结构、时间复杂度、空间复杂度

后续可能会有补充和更改 目录 一、数据结构 1.算法介绍 二、时间复杂度、空间复杂度 三、练习 1.时间复杂度 2.空间复杂度 一、数据结构 数据结构是计算机存储、组织数据的方式&#xff0c;指相互之间存在一种或多种特定关系的数据元素的集合。 数据结构和数据库的区…...

abstract class和interface有什么区别?

含有abstract修饰符的class即为抽象类&#xff0c;abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class&#xff0c;abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现&#xff0c;所以&#xf…...

Kafka在Java项目中的应用

Kafka在Java项目中的应用 Docker 安装Kafka 一.首先需要安装docker,可看这篇文章安装docker 二.拉取zookeeper和KafKa镜像 docker pull wurstmeister/zookeeperdocker pull wurstmeister/kafkaKafka组件需要向zookeeper进行注册,所以也需要安装zookeeper 三.启动zookeeper…...

理解分布式id生成算法SnowFlake

理解分布式id生成算法SnowFlake 分布式id生成算法的有很多种&#xff0c;Twitter的SnowFlake就是其中经典的一种。 概述 SnowFlake算法生成id的结果是一个64bit大小的整数&#xff0c;它的结构如下图&#xff1a; } public function __construct(){ $this->rnew…...

光纤收发器可以连接光模块吗?

随着科技的进步发展&#xff0c;城市信息化速度的加快&#xff0c;光通信产品在数据中心和安防监控等场景中的运用越来越广泛&#xff0c;而这之间的连接则需要光模块和光纤收发器来实现。很多用户对光模块和光纤收发器的使用有些疑虑&#xff0c;两者该如何连接&#xff1f;又…...

一文快速了解浏览器Sui Explorer

Sui作为一条基于第一原理重新设计和构建而成的L1公链&#xff0c;所有区块和交易信息皆公开透明&#xff0c;每个人都能自行查看。通过Sui链上浏览器&#xff0c;用户可以迅速了解链上的交易情况&#xff0c;比如当前的TPS和Gas价格&#xff0c;也可以使用Digest来查看特定交易…...

python中lambda、yield、map、filter、reduce的使用

1、 匿名函数lambda python中允许使用lambda关键字定义一个匿名函数。所谓的匿名函数就是说使用一次或者几次之后就不再需要的函数&#xff0c;属于“一次性”函数。 #例1&#xff1a;求两数之和 f lambda x, y: x y print(f(5, 1))#例2&#xff1a;求平方和 print((lambda…...

第十八章 使用LNMP架构部署动态网站环境

文章目录 第十八章 使用LNMP架构部署动态网站环境一、源码包程序1、源码包的优势2、基本步骤&#xff08;1&#xff09;、下载及解压源码包文件&#xff08;2&#xff09;、编译源码包代码&#xff08;3&#xff09;、生成二进制安装程序&#xff08;4&#xff09;、运行二进制…...

无人值守的IDC机房动环综合运维方案

企业数字化转型以及5G、物联网、云计算、人工智能等新业态带动了数据中心的发展&#xff0c;在国家一体化大数据中心及“东数西算”节点布局的推动下&#xff0c;数据中心机房已成为各大企事业单位维持业务正常运营的重要组成部分&#xff0c;网络设备、系统、业务应用数量与日…...

桌面远程工具推荐

目前市面上的远程工具多如牛毛&#xff0c;很多人不知道怎么选择&#xff0c;下面小编介绍两种桌面远程工具&#xff0c;它们都是跨平台的&#xff0c;均支持Windows&#xff0c;Mac OS&#xff0c;IOS和安卓&#xff0c;分别是RayLink&#xff0c;VNC&#xff0c;好用&#xf…...

MySQL高级——第15章_锁

第15章_锁 1. 概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在程序开发中会存在多线程同步的问题&#xff0c;当多个线程并发访问某个数据的时候&#xff0c;尤其是针对一-些敏感的数据(比如订单、金额等)&#xff0c;我们就需要保证这个数据在任何 时刻最多只…...

【ROS】Ubuntu22.04安装ROS2(Humble Hawksbill)

0、版本说明 Ubuntu22.04对应的ROS2的版本为Humble Hawksbill&#xff08;ros-humble&#xff09; 如果不是在Ubuntu22.04中安装ROS&#xff0c;请参考下面Ubuntu和ROS的版本对应关系 1、更新apt包列表 $ sudo apt update2、设置编码 将ubuntu环境语言编码设置为en_US en_…...

【ChatGPT】体验一下ChatGPT

体验一下ChatGPT 可以帮你写代码、写邮件、编故事的神器 最近OpenAI 发布了备受期待的原型通用 ChatGPT&#xff0c;这是一种基于对话的 AI 聊天界面&#xff0c;算是GPT-3(Generative Pre-trained Transformer 3)的继承者&#xff0c;今天记录一下体验的过程&#xff0c;以前…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...