【888题竞赛篇】第五题,2023ICPC澳门-传送(Teleportation)

这里写自定义目录标题

  • 更多精彩内容
    • 256题算法特训课,帮你斩获大厂60W年薪offer
  • 原题
    • 2023ICPC澳门真题传送
    • B站动画详解
  • 问题分析
  • 思路分析
      • 图的构建
      • 最短路径算法
      • 具体步骤
  • 算法实现
      • Dijkstra 算法
      • 图的构建
  • 代码详解
    • 标准代码程序
      • C++代码
      • Java代码
      • Python代码
      • Javascript代码
  • 复杂度分析
    • 时间复杂度
    • 空间复杂度
  • 总结

更多精彩内容

这里是带你游历编程世界的Dashcoding编程社,我是Dash/北航硕士/ICPC区域赛全国排名30+/给你呈现我们眼中的世界!

256题算法特训课,帮你斩获大厂60W年薪offer

原题

2023ICPC澳门真题传送

B站动画详解

问题分析

题目要求从房间 0 0 0 到达房间 x x x 的最小能量消耗。可以进行两种操作:传送到房间 ( i + a i ) % n (i + a_i) \% n (i+ai)%n 或者增加当前房间的数值 a i a_i ai。每次操作都消耗一点能量,问题的本质是一个最短路径问题。

这个问题可以通过图论中的单源最短路径算法来解决。我们将每个房间视为图中的节点,操作视为从一个节点到另一个节点的边,求解从节点 0 0 0 到节点 x x x 的最短路径。

思路分析

图的构建

  1. 传送操作
    如果在房间 i i i 进行传送操作,可以跳到房间 ( i + a i ) % n (i + a_i) \% n (i+ai)%n。因此,这个操作在图中表示为一条从节点 i i i 到节点 ( i + a i ) % n (i + a_i) \% n (i+ai)%n 的有向边,权值为 1 1 1

  2. 数值增加操作
    如果选择增加房间的数值 a i ← a i + 1 a_i \leftarrow a_i + 1 aiai+1,则可以使得下次传送跳到下一个房间,因此在图中可以加入一条从房间 i i i 到房间 i + 1 i + 1 i+1 的边,权值也为 1 1 1

  3. 特殊处理房间 0 0 0
    为了处理房间 0 0 0 的特殊情况(即只有在第二次及以后回到房间 0 0 0 时,才会从 0 0 0 引出一条边到 1 1 1),我们引入一个额外的节点 n n n,表示从 0 0 0 多次到达的状态。

最短路径算法

使用 Dijkstra 算法来计算从节点 0 0 0 到节点 x x x 的最短路径。Dijkstra 算法适用于具有非负权值的图,在该题中,每条边的权值为 1 1 1,正好符合该算法的要求。

具体步骤

  1. 初始化图,将每个节点与其对应的边构建好。
  2. 运行 Dijkstra 算法,计算从节点 0 0 0 出发到所有节点的最短路径。
  3. 输出节点 x x x 的最短距离,即为答案。

算法实现

Dijkstra 算法

Dijkstra 算法是一种贪心算法,用于解决单源最短路径问题。它通过优先队列(最小堆)来确保每次扩展的节点是当前距离最短的节点,从而保证计算出的路径是最优的。在本题中,我们将图中的每条边的权值设为 1 1 1,因此算法能够高效地计算最短路径。

图的构建

对于每个房间 i i i,我们有两种操作:

  1. 传送到房间 ( i + a i ) % n (i + a_i) \% n (i+ai)%n,这在图中表示为一条从节点 i i i 到节点 ( i + a i ) % n (i + a_i) \% n (i+ai)%n 的边。
  2. 增加数值 a i a_i ai 后,可以使得下一次传送跳到下一个房间。因此,我们加入一条从节点 i i i 到节点 i + 1 i + 1 i+1 的边。

另外,为了处理房间 0 0 0 的特殊情况,我们加入了一个节点 n n n,用来表示从房间 0 0 0 多次到达的状态。

代码详解

标准代码程序

C++代码

#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
const int N = 1e5 + 10;
vector<pair<int,int>> G[N];  // 图的邻接表
int dis[N], a[N], vis[N], n, x;// Dijkstra 算法求单源最短路径
void dij(int st, int *dis) {for(int i = 0; i <= n; i++) {vis[i] = 0;dis[i] = INT_MAX;}priority_queue<pair<int,int>> q;dis[st] = 0;q.push({0, st});while(q.size()) {int w = -q.top().first;int u = q.top().second;q.pop();if(vis[u]) continue;vis[u] = 1;for(auto v : G[u]) {int to = v.first;int s = v.second;if(dis[to] > w + s) {dis[to] = w + s;q.push({-dis[to], to});}}}
}int main() {cin >> n >> x;for(int i = 0; i < n; i++) cin >> a[i];// 构建图for(int i = 0; i <= n; i++) {int to = (i + a[i % n]) % n;if(to == 0) to = n;  // 处理到达 0 的情况G[i].push_back({to, 1});if(i >= 1) {  // 增加数值后的操作to = i + 1;if(to > n) to = 1;G[i].push_back({to, 1});}}// 运行 Dijkstra 算法dij(0, dis);// 输出结果cout << dis[x];
}

Java代码

import java.util.*;public class Main {static class Pair implements Comparable<Pair> {int dist, node;Pair(int dist, int node) {this.dist = dist;this.node = node;}@Overridepublic int compareTo(Pair other) {return Integer.compare(this.dist, other.dist);}}static final int N = 100010;static List<Pair>[] G = new ArrayList[N];static int[] dis = new int[N], a = new int[N], vis = new int[N];static int n, x;static void dijkstra(int st) {Arrays.fill(vis, 0);Arrays.fill(dis, Integer.MAX_VALUE);PriorityQueue<Pair> pq = new PriorityQueue<>();dis[st] = 0;pq.add(new Pair(0, st));while (!pq.isEmpty()) {Pair p = pq.poll();int w = p.dist, u = p.node;if (vis[u] == 1) continue;vis[u] = 1;for (Pair v : G[u]) {int to = v.node, s = v.dist;if (dis[to] > w + s) {dis[to] = w + s;pq.add(new Pair(dis[to], to));}}}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();x = sc.nextInt();for (int i = 0; i <= n; i++) G[i] = new ArrayList<>();for (int i = 0; i < n; i++) a[i] = sc.nextInt();for (int i = 0; i <= n; i++) {int to = (i + a[i % n]) % n;if (to == 0) to = n;G[i].add(new Pair(1, to));if (i >= 1) {to = i + 1;if (to > n) to = 1;G[i].add(new Pair(1, to));}}dijkstra(0);System.out.println(dis[x]);}
}

Python代码

import heapqdef dijkstra(st, n, G):dis = [float('inf')] * (n + 1)vis = [False] * (n + 1)dis[st] = 0pq = [(0, st)]  # (distance, node)while pq:w, u = heapq.heappop(pq)if vis[u]:continuevis[u] = Truefor v, s in G[u]:if dis[v] > w + s:dis[v] = w + sheapq.heappush(pq, (dis[v], v))return disdef main():n, x = map(int, input().split())a = list(map(int, input().split()))G = [[] for _ in range(n + 1)]for i in range(n):to = (i + a[i % n]) % nif to == 0:to = nG[i].append((to, 1))if i >= 1:to = i + 1if to > n:to = 1G[i].append((to, 1))dis = dijkstra(0, n, G)print(dis[x])if __name__ == "__main__":main()

Javascript代码

function dijkstra(st, n, G) {const dis = Array(n + 1).fill(Infinity);const vis = Array(n + 1).fill(false);const pq = [[0, st]]; // [distance, node]dis[st] = 0;while (pq.length) {pq.sort((a, b) => b[0] - a[0]); // Max-heap simulated with sortingconst [w, u] = pq.pop();if (vis[u]) continue;vis[u] = true;for (const [v, s] of G[u]) {if (dis[v] > w + s) {dis[v] = w + s;pq.push([dis[v], v]);}}}return dis;
}function main() {const [n, x] = prompt().split(' ').map(Number);const a = prompt().split(' ').map(Number);const G = Array.from({ length: n + 1 }, () => []);for (let i = 0; i < n; i++) {let to = (i + a[i % n]) % n;if (to === 0) to = n;G[i].push([to, 1]);if (i >= 1) {to = i + 1;if (to > n) to = 1;G[i].push([to, 1]);}}const dis = dijkstra(0, n, G);console.log(dis[x]);
}main();

复杂度分析

时间复杂度

Dijkstra 算法的时间复杂度为 O ( ( n + m ) log ⁡ n ) O((n + m) \log n) O((n+m)logn),其中 m m m 是边的数量。在本题中,图中的边数量近似为 2 n 2n 2n,所以复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn)

空间复杂度

图的存储空间为 O ( n ) O(n) O(n),距离数组和访问标记数组的空间也为 O ( n ) O(n) O(n),因此总体空间复杂度为 O ( n ) O(n) O(n)

总结

本题通过将问题转化为图论中的最短路径问题,并使用 Dijkstra 算法来高效求解。算法的关键在于合理构建图结构,并充分考虑不同操作的边权关系。通过引入虚拟节点,处理特殊情况,使得问题的求解更加简洁明了。这种图论思想在处理类似问题时具有广泛应用,特别是在路径规划与最优决策问题中。

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

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

相关文章

pycharm中gurobi使用指南-变量类型及声明

文章目录 Gurobi 变量声明&#xff1a;全面指南与示例gurobi声明变量的数学含义整数变量&#xff08;Integer Variable&#xff09;定义数学表示示例 二元变量&#xff08;Binary Variable&#xff09;定义数学表示示例 连续变量&#xff08;Continuous Variable&#xff09;定…

EasyCVR视频汇聚平台构建远程安防监控:5大亮点解析,助力安防无死角

随着科技的飞速发展&#xff0c;远程安防监控系统已经成为现代社会中不可或缺的一部分&#xff0c;无论是在小区、公共场所还是工业领域&#xff0c;安防监控都发挥着至关重要的作用。而EasyCVR作为一款功能强大的视频监控综合管理平台&#xff0c;其在构建远程安防监控系统方面…

电测量数据交换DLMS∕COSEM组件第62部分:COSEM接口类(4)

1.7COSEM服务器模型 COSEM服务器被构建为3层体系结构如图3所示。 图4示例说明如何用COSEM服务器模型构建一台组合式计量设备。 1.8COSEM逻辑设备 1.8.1概述 COSEM逻辑设备包含一组COSEM对象,每个物理设备均应包含一个“Management logical device”。对COSEM逻辑设备…

2024华为OD机试真题- 贪吃的猴子Python-C卷D卷-200分

目录 题目描述 输入描述 输出描述 用例1 用例2 用例3 解题思路 代码 2024华为OD机试题库-(C卷+D卷)-(JAVA、Python、C++) 题目描述 一只贪吃的猴子,来到一个果园,发现许多串香蕉排成一行,每串香蕉上有若干根香蕉。每串香蕉的根数由数组numbers给出。 猴子获取香蕉,…

大模型之战-操作数据表-coze

工作流直接操作数据库啦【何时可以直接访问自己的数据库呢】 1&#xff0c;第一步创建一个bot智能体 1.1&#xff0c;bot中创建数据库表&#xff1a; 1.2&#xff0c;智能体可以通过对话&#xff0c;操作表&#xff1b;【增加&#xff0c;筛选查询等】 1.2.1&#xff0c;增加…

Java--SpringBoot工厂模式

工厂模式 Spring Boot是一个基于Spring框架的快速开发框架&#xff0c;它提供了许多便利的功能来简化企业级应用的开发。在Spring Boot中&#xff0c;工厂模式是一种常用的设计模式&#xff0c;它用于创建对象&#xff0c;但是不需要指定将要创建的具体类。工厂模式隐藏了实例…

Transformer(课程笔记)

一&#xff1a;Motivation RNN需要顺序的执行&#xff0c;不利于并行计算。 RNN的变体例如GRU、LSTM等需要依靠注意力机制解决信息瓶颈等问题。 抛弃RNN结构&#xff0c;提出了Transformer结构。 Transformer整体架构 二&#xff1a; 输入层&#xff08;BPE&#xff0c;PE&…

第2章-01-网站中的资源介绍

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲。 🎉欢迎 👍点赞✍评论⭐收…

西北乱跑娃 -- linux使用笔记

1.后台运行每天一个日志文件 nohup python3.8 manage.py >> $(date %Y-%m-%d).log 2>&1 &2.目录操作&#xff1a; ls&#xff1a;列出目录内容。cd&#xff1a;改变当前工作目录。pwd&#xff1a;显示当前工作目录的路径。mkdir&#xff1a;创建新目录。rmd…

Linux下查看各进程的swap

cat /etc/re*se Red Hat Enterprise Linux Server release 6.8 (Santiago) 简单的可以通过top命令查看 top 后 按 f 进入选择列界面 按 p 就会输出swap信息&#xff08;变为P&#xff09; 回车返回看到SWAP信息了 再按 F 再按p 按swap排序 再回车后就是各进程按swap排序…

linux:进程优先级、环境变量、地址空间

进程优先级 什么叫进程优先级&#xff1f; 进程优先级是指进程获取某些资源的先后顺序 上文中的task_struct&#xff0c;也叫进程控制块&#xff08;PCB&#xff09;&#xff0c;本质上是结构体&#xff0c;我们的优先级就被写在结构体里面&#xff08;内部字段&#xff09;…

wordpress站群搭建6外部库的引入和测试

wordpress站群搭建6wordpress外部库的引入和测试 本次目标我们主要讲解引入wordpress外部库并测试。 我们将一些外部库和工具包放入到pkg项目&#xff0c;方便其他项目引用。 1.安装go-wordpress库 进入到pkg项目 go get github.com/robbiet480/go-wordpress2.编写工具类 …

华为的流程管理

华为建设流程体系始于2000年&#xff0c;那时华为公司面临着快速扩张和全球化发展的挑战&#xff0c;意识到传统的管理模式已经无法满足业务发展的需求。为了提高公司的管理效率和竞争优势&#xff0c;华为决定启动流程体系的建设。在建设过程中&#xff0c;华为借鉴了业界最佳…

Linux命令grep -R

1. Linux 命令grep -R 的基本用法如下。 功能&#xff1a;主要用来搜索指定目录下的所有文件是否包含某个文本等等。 特点: 递归查询. 2. 特殊发现 今天使用时发现&#xff0c;这个命令同样可以从.a&#xff0c;.so 等各种动静态库 搜索出文本&#xff0c; 缺点是没有没有列举…

橙色简洁大气体育直播自适应模板赛事直播门户自适应网站源码

源码名称&#xff1a;酷黑简洁大气体育直播自适应模板赛事直播门户网站 源码开发环境&#xff1a;帝国cms 7.5 安装环境&#xff1a;phpmysql 带采集&#xff0c;可以挂着电脑上自动采集发布&#xff0c;无需人工操作&#xff01; 橙色简洁大气体育直播自适应模板赛事直播门户…

Redis的基本概念和使用

目录 一、Redis简介 1、NOSQL 2、NOSQL和关系型数据库比较 3、主流的NOSQL产品 4、什么是Redis 5、启动Redis 二、Redis基本操作 1、大概操作 三、 Redis 数据类型&#xff08;5种常用&#xff09; 1、redis 数据存储格式 2、String 3、hash 4、list 5、Set 6、…

Hadoop大数据分析案例

目录 案例概述环境搭建1. Hadoop单机环境2. Hadoop集群环境 数据集数据预处理 MapReduce作业编写提交作业 数据可视化可能遇到的问题及解决方法结论 案例概述 本案例将详细介绍如何在单机和集群环境下使用Hadoop进行大数据分析&#xff0c;最后利用Python进行数据的可视化展示…

音频剪辑软件哪个好用?五大音频剪辑软件分享

如果你正打算在家自学视频制作&#xff0c;那么恭喜你&#xff0c;你已经踏上了一段充满魔法与惊喜的旅程&#xff01;不过&#xff0c;别忘了&#xff0c;视频的灵魂不仅仅在于画面&#xff0c;更在于那直击心灵的音效。 想象一下&#xff0c;一个精心剪辑的片段&#xff0c;…

gt接口的Alignment, Termination, and Equalization界面配置配置了什么

在GT接口的Alignment, Termination, and Equalization界面配置中&#xff0c;主要涉及到两个关键部分的配置&#xff1a;逗号对齐&#xff08;Comma Alignment&#xff09;和均衡处理&#xff08;Termination and Equalization&#xff09;。以下是对这两个部分的详细解释&…

汇编语言中的高效引擎:深入理解流水线技术

标题&#xff1a;汇编语言中的高效引擎&#xff1a;深入理解流水线技术 引言 在现代计算机架构中&#xff0c;流水线&#xff08;Pipeline&#xff09;是一种允许多个指令同时在处理阶段中前进的技术&#xff0c;极大地提高了处理器的效率和性能。在汇编语言层面理解流水线&a…