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

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

相关文章:

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

这里写自定义目录标题 更多精彩内容256题算法特训课&#xff0c;帮你斩获大厂60W年薪offer 原题2023ICPC澳门真题传送B站动画详解 问题分析思路分析图的构建最短路径算法具体步骤 算法实现Dijkstra 算法图的构建 代码详解标准代码程序C代码Java代码Python代码Javascript代码 复…...

javascript写一个页码器-SAAS本地化及未来之窗行业应用跨平台架构

一代码 接引入 <script type"text/javascript" src"CyberWin_APP_Page.js" alt"未来之窗页码"></script>function 未来之窗页面触发器(页码){console.log("当前用户新"页码);}CyberWin_Page.set_callback(未来之窗页面触发…...

微信小程序如何自定义一个组件

微信小程序支持组件化开发&#xff0c;这有助于我们复用代码&#xff0c;提高开发效率。下面我将给出一个简单的微信小程序组件化示例&#xff0c;包括一个自定义组件的创建和使用。 1. 创建自定义组件 首先&#xff0c;在项目的 components 目录下创建一个新的组件文件夹&am…...

【数学建模备赛】Ep05:斯皮尔曼spearman相关系数

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、斯皮尔曼spearman相关系数&#xff1a;☀️☀️☀️1. 回顾皮尔逊相关系数2. 斯皮尔曼spearman相关系数3. 斯皮尔曼相关系数公式4. 另外一种斯皮尔曼相关系数定义5. matlab的用法5. matlab的用法 三、对斯皮尔曼相…...

MATLAB进行神经网络建模的案例

下面是一个使用MATLAB进行神经网络建模的案例&#xff0c;该案例涉及使用神经网络来逼近一个未知系统的输入输出关系。这个案例与您提到的学习资料中的实例类似&#xff0c;但我会简化并解释每个步骤。 案例背景 假设我们有一组输入和输出数据&#xff0c;我们希望通过建立一…...

每天一个数据分析题(四百八十九)- 主成分分析与因子分析

关于主成分分析和因子分析的区别&#xff0c;下列描述正确的是&#xff08; &#xff09; A. 主成分分析是一种无监督学习算法&#xff0c;而因子分析是一种有监督学习算法 B. 主成分分析是一种线性变换方法&#xff0c;而因子分析是一种非线性变换方法 C. 主成分分析的结果…...

Java RPC、Go RPC、Node RPC、Python RPC 之间的互相调用

Java RPC、Go RPC、Node RPC、Python RPC 之间的互相调用是完全可以实现的&#xff0c;但需要满足一些条件和依赖于特定的工具和协议。以下是如何实现不同语言之间的RPC互相调用的详细解释&#xff1a; 1. 使用通用协议和标准&#xff1a;gRPC gRPC 是一个高性能、开源的RPC框…...

国外代理IP选择:IP池的大小有何影响

代理IP是跨境人不可或缺的工具&#xff0c;广泛应用于广告验证、数据获取和账号矩阵管理等方面。而在选择代理IP时&#xff0c;IP池的大小往往是一个至关重要的考量因素。本文将深入解析IP池大小对代理IP选择的影响&#xff0c;帮助大家更好地理解这一关键决策点。 一、IP池的…...

手机谷歌浏览器怎么用

谷歌浏览器不仅在PC端受欢迎&#xff0c;在移动端也是广泛应用的。为了帮助大家更好的理解和使用手机谷歌浏览器&#xff0c;本文将详细介绍如何使用手机谷歌浏览器&#xff0c;对这款浏览器感到陌生的话就快快学起来吧。&#xff08;本文由https://chrome.cmrrs.com/站点的作者…...

Button窗口部件

# 2. Button窗口部件 # 简单说明&#xff1a; # Button&#xff08;按钮&#xff09;部件是一个标准的Tkinter窗口部件&#xff0c;用来实现各种按钮。按钮能够包含文本或图象&#xff0c; # 并且你能够将按钮与一个Python函数或方法相关联。当这个按钮被按下时&#xff0c;Tki…...

PCIe学习笔记(25)

数据完整性 PCI Express的基本数据可靠性机制包含在数据链路层(data Link Layer)中&#xff0c;它使用32位的LCRC (CRC)码逐链路检测TLP中的错误&#xff0c;并采用逐链路重传机制进行错误恢复。TLP是一个数据和事务控制单元&#xff0c;由位于PCI Express域“边缘”的数据源(…...

8.20

上午 1、使用ansible安装并启动ftp服务 [root1 ~]# vim /etc/ansible/hosts s0 ansible_ssh_host10.0.0.12 ansible_ssh_port22 ansible_ssh_userroot ansible_ssh_pass1 s1 ansible_ssh_host10.0.0.13 ansible_ssh_port22 ansible_ssh_userroot ansible_ssh_pass1 s2 ansi…...

centos7.9系统安装talebook个人书库

1.简介&#xff1a; talebook —— 一个基于Calibre的简单的个人图书管理系统&#xff0c;支持在线阅读。 2.环境准备&#xff1a; #使用阿里源 wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo #安装docker yu…...

ES高级查询Query DSL查询详解、term术语级别查询、全文检索、highlight高亮

文章目录 ES高级查询Query DSLmatch_all返回源数据_source返回指定条数size分页查询from&size指定字段排序sort 术语级别查询term query术语查询terms query多术语查询range query范围查询exists queryids queryprefix query前缀查询wildcard query通配符查询fuzzy query模…...

关于Blender云渲染农场,你应该知道的一切!

Blender是一个功能强大的免费开源3D创作套件&#xff0c;提供了广泛的工具和特性&#xff0c;因此受到了许多3D艺术家的喜爱。在创建3D场景的过程中&#xff0c;渲染作为最后一步&#xff0c;常常是许多艺术家头疼的问题&#xff0c;因为它不仅耗时&#xff0c;还占用了他们的计…...

Obsidian如何安装插件

文章目录 前言开始安装写在最后 前言 没有插件的 Obsidian 是不完整的 Obsidian&#xff0c;如果你正在使用 Obsidian&#xff0c;一定要会安装插件。 本文将告诉你如何安装 Obsidian 第三方插件。 开始安装 首先进入 Obsidian 界面。 点击左下角的设置图标&#xff0c;就…...

Nginx服务器申请及配置免费SSL证书

免费SSL证书申请 背景&#xff1a; 我的情况是这样&#xff0c;域名解析是华为云的&#xff0c;然后免费证书在腾讯云申请。但是大致的配置流程都是一样的 在腾讯云平台申请免费的SSL证明(目前有效期是9天)&#xff0c;申请步骤如下 主要步骤说明 申请免费SSL证书配置证书到域…...

STM32CubeMX 配置串口通信 HAL库

一、STM32CubeMX 配置串口 每个外设生成独立的 ’.c/.h’ 文件 不勾&#xff1a;所有初始化代码都生成在 main.c 勾选&#xff1a;初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。 二、重写fputc函数 ​ #include <stdio.h>#ifdef __GNUC__#def…...

GitHub的未来:在微软领导下保持独立与AI发展的平衡

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

RGB与YUV格式详解

图像处理 文章目录 图像处理前言一、RGB格式二、YUV格式三、RGB与YUV转换四、NV21转换为YUV420p五、YUV旋转 前言 在图像的世界里&#xff0c;一般使用RGB作为存储格式。而在视频的世界里&#xff0c;一般使用YUV作为压缩存储格式。有时候面试官会问&#xff1a;为什么视频使用…...

JS获取当前浏览器名称

在JavaScript中&#xff0c;获取当前浏览器名称的方法并不是一个标准的功能&#xff0c;因为浏览器厂商并没有提供一个直接的API来获取浏览器的名称。但是&#xff0c;你可以通过分析用户代理字符串&#xff08;User-Agent&#xff09;来推断出浏览器的名称。 以下是一个简单的…...

学习计算机网络(五)——ICMP协议

ICMP 协议&#xff08;Internet Control Message Protocol&#xff0c;互联网控制报文协议&#xff09;&#xff0c;主要用于在 IP 网络中传递控制消息和差错报告。 ICMP在IP系统间传递差错和管理报文&#xff0c;是任何IP实现必需和要求的组成部分。 可把ICMP报文分成两类&a…...

request.getRequestURI()与request.getRequestURL()的区别

1.返回值的区别&#xff1a; request.getRequestURL() 返回值是一个StringBuffer类型 request.getRequestURI() 返回值是一个String类型 先看 request.getRequestURL() 返回的是一个具体的地址&#xff0c;访问网页的地址 而 request.getRequestURI() 返回的是一个映射地址&a…...

3154. 到达第 K 级台阶的方案数(24.8.20)

今天发晚了&#xff0c;嘿嘿&#xff0c;玩黑神话玩的 题目 给你有一个 非负 整数 k 。有一个无限长度的台阶&#xff0c;最低 一层编号为 0 。 Alice 有一个整数 jump &#xff0c;一开始值为 0 。Alice 从台阶 1 开始&#xff0c;可以使用 任意 次操作&#xff0c;目标是到达…...

如何使用docker打包后端项目并部署到阿里云k8s集群上

如何使用docker打包后端项目并部署到阿里云k8s集群上 1. 引言 在现代软件开发中,容器化技术已经成为主流,而Kubernetes (K8s) 是管理容器的首选平台之一。本文将详细介绍如何将一个后端项目使用Docker打包,并将其部署到阿里云的Kubernetes集群上。 2. 前置条件 阿里云账号…...

ES6中解构的使用

一、提取几个属性&#xff0c;构造一个新的对象 在JavaScript中&#xff0c;你可以使用对象解构&#xff08;Object Destructuring&#xff09;来提取一个对象中的几个属性&#xff0c;并构造一个新的对象。下面是一个示例&#xff1a; 在这个例子中&#xff0c;name和email属性…...

拖拽式报表设计器优点好 实现流程化办公就靠它!

当前&#xff0c;实现流程化办公是很多企业都想要实现的目标。利用低代码技术平台、拖拽式报表设计器的优势特点&#xff0c;可以为企业降低开发成本、提升办公效率、创造更多市场价值。那么&#xff0c;您知道拖拽式报表设计器的优点是什么吗&#xff1f;通过本文一起了解拖拽…...

Spring项目:文字花园(四)

一.实现登录 传统思路: • 登陆⻚⾯把⽤⼾名密码提交给服务器. • 服务器端验证⽤⼾名密码是否正确, 并返回校验结果给后端 • 如果密码正确, 则在服务器端创建 Session . 通过 Cookie 把 sessionId 返回给浏览器. 问题: 集群环境下⽆法直接使⽤Session. 原因分析: 我们开…...

Web开发:ORM框架之Freesql的入门和技巧使用小结

目录 零、官网链接 一、字段映射表 二、查询 1.freesql独特封装&#xff1a;between关键字 2.分页&#xff08;每页 20 条数据&#xff0c;查询第 1 页&#xff09; 3.Withsql&#xff08;子查询&#xff0c;不建议&#xff09; 3.简单查询、映射查询 4.参数查询、自定义…...

软件工程(4)面向对象方法:面向对象软件工程OOSE与案例实践

OOSE&#xff08;Object-Oriented Software Engineering&#xff0c;面向对象软件工程&#xff09;是一种用于开发软件系统的工程方法论&#xff0c;它强调使用面向对象的技术和方法来设计和实现软件。OOSE 方法是由 Ivar Jacobson 提出的&#xff0c;主要包括以下几个关键方面…...