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

2023年CSP入门级第二轮第四题——旅游巴士

概要

题目描述
小 Z 打算在国庆假期期间搭乘旅游巴士去一处他向往已久的景点旅游。

旅游景点的地图共有 n 处地点,在这些地点之间连有 m 条道路。其中 1 号地点为景区入口,n 号地点为景区出口。我们把一天当中景区开门营业的时间记为 0 时刻,则从 0 时刻起,每间隔 k 单位时间便有一辆旅游巴士到达景区入口,同时有一辆旅游巴士从景区出口驶离景区。

所有道路均只能单向通行。对于每条道路,游客步行通过的用时均为恰好 1 单位时间。

小 Z 希望乘坐旅游巴士到达景区入口,并沿着自己选择的任意路径走到景区出口,再乘坐旅游巴士离开,这意味着他到达和离开景区的时间都必须是 k 的非负整数倍。由于节假日客流众多,小 Z 在旅游巴士离开景区前只想一直沿着景区道路移动,而不想在任何地点(包括景区入口和出口)或者道路上停留。

出发前,小 Z 忽然得知:景区采取了限制客流的方法,对于每条道路均设置了一个 “开放时间”ai ,游客只有不早于 ai 时刻才能通过这条道路。

请帮助小 Z 设计一个旅游方案,使得他乘坐旅游巴士离开景区的时间尽量地早。

输入格式
输入的第一行包含 3 个正整数 n,m,k,表示旅游景点的地点数、道路数,以及旅游巴士的发车间隔。

输入的接下来 m 行,每行包含 3 个非负整数 ui ,vi,ai ,表示第 i 条道路从地点 ui 出发,到达地点 vi,道路的“开放时间”为 ai。

输出格式
输出一行,仅包含一个整数,表示小 Z 最早乘坐旅游巴士离开景区的时刻。如果不存在符合要求的旅游方案,输出 -1。

输入输出样例
输入 #1

5 5 3
1 2 0
2 5 1
1 3 0
3 4 3
4 5 1
输出 #1

6
说明/提示
【样例 #1 解释】

小 Z 可以在 3 时刻到达景区入口,沿 1→3→4→5 的顺序走到景区出口,并在 6 时刻离开。
在这里插入图片描述

优先队列代码

#include <bits/stdc++.h>
using namespace std;
const int M=101,N=1e4+5;
int n,m,T,t[M][N];
bool k[M][N];
vector<pair<int,int>> v[N];//各景点所通道路并开方时间 
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;//优先队列 
int main(){//freopen("data.cpp","r",stdin);cin>>n>>m>>T;for(int i=0;i<m;i++){int sx,ex,tx;cin>>sx>>ex>>tx;v[sx].push_back({tx,ex});}memset(t,0x3f3f3f,sizeof(t));//找所经更少时间 t[0][1]=0;q.push({0,1});while(!q.empty()){//宽搜 int st=q.top().first,sx=q.top().second;q.pop();//到达该景点的时间 if(k[st%T][sx])continue;k[st%T][sx]=1;//这个点从这个景点出发过了 for(int i=0;i<v[sx].size();i++){//该景点通往其他景点的道路 int et=v[sx][i].first,ex=v[sx][i].second,tx;//该道路通行时间和目的景点 if(st>=et)tx=st;//通行后才到,刚好 else tx=ceil((et-st)*1.0/T)*T+st;//离通行时间差几趟bus, 那就等开通后再来,就是 if(t[(tx+1)%T][ex]>tx+1){//只记是一天中的几点到该景区的最少用时 t[(tx+1)%T][ex]=tx+1;q.push({tx+1,ex});}if(k[0][n]){break;break;} }}if(k[0][n])cout<<t[0][n];else cout<<-1;return 0;
}

宽搜

#include <bits/stdc++.h>
using namespace std;
const int M=101,N=1e4+5;
int n,m,T,t[M][N];
bool k[M][N];
vector<pair<int,int>> v[N];//各景点所通道路并开方时间 
queue<pair<int,int>> q;//优先队列 
int main(){//freopen("data.cpp","r",stdin);cin>>n>>m>>T;for(int i=0;i<m;i++){int sx,ex,tx;cin>>sx>>ex>>tx;v[sx].push_back({tx,ex});}memset(t,0x3f3f3f,sizeof(t));//找所经更少时间 t[0][1]=0;q.push({0,1});while(!q.empty()){//宽搜 int st=q.front().first,sx=q.front().second;q.pop();//到达该景点的时间 //if(k[st%T][sx])continue;k[st%T][sx]=1;//这个点从这个景点出发过了 for(int i=0;i<v[sx].size();i++){//该景点通往其他景点的道路 int et=v[sx][i].first,ex=v[sx][i].second,tx;//该道路通行时间和目的景点 if(st>=et)tx=st;//通行后才到,刚好 else tx=ceil((et-st)*1.0/T)*T+st;//离通行时间差几趟bus, 那就等开通后再来,就是 if(t[(tx+1)%T][ex]>tx+1){//只记是一天中的几点到该景区的最少用时 t[(tx+1)%T][ex]=tx+1;q.push({tx+1,ex});}}}if(t[0][n]!=0x3f3f3f)cout<<t[0][n];else cout<<-1;return 0;
}

非满分,不知哪里有问题。

关于时间归拢

在这里插入图片描述

小结

就是宽搜题,从1出发各个景点,直到n景点。
难处理的地方是把到达各个景点的最少时间归拢到bus周期内。如今天到该景点,景点通往别景点的道路已通行,则成行。否则就得明天这时间来才能进(如,一天一趟车)。
所以归拢时间是((放行时间-到达时间)/bus间隔时间)——几个间隔时间,乘以间隔时间+到达时间。
用优先队列,第一次到达n景点的时间就是最少时间。否则得全部遍历。
不归拢到bus周期得话考虑的时间太多,也没必要。

http://www.dtcms.com/a/287120.html

相关文章:

  • windows wsl2-06-docker hello world
  • 网络原理——TCP
  • 【学习记录】智能客服小桃(进度更新ing)
  • 张 关于大语言模型(LLM)置信度研究的经典与前沿论文 :温度缩放;语义熵;自一致性;事实与反思;检索增强;黑盒引导;
  • 软考 系统架构设计师系列知识点之杂项集萃(113)
  • LangGraph教程10:LangGraph ReAct应用
  • 基于Electron打包jar成Windows应用程序
  • 技术演进中的开发沉思-39 MFC系列:多重文件和多重视图
  • 安全事件响应分析--基础命令
  • 【52】MFC入门到精通——(CComboBox)下拉框选项顺序与初始化不一致,默认显示项也不一致
  • pytorch:tensorboard和transforms学习
  • HTML5中的自定义属性
  • Jenkins自动化部署.NET应用实战:Docker+私有仓库+SSH远程发布
  • mysql常用总结
  • EMC杂谈-001-基础知识
  • 【面试八股文】软件测试面试题汇总
  • [黑马头条]-项目整合对象存储服务MinIO
  • 百度网盘TV版1.21.0 |支持倍速播放,大屏云看片
  • CS231n-2017 Lecture2图像分类笔记
  • 工业企业与污染库匹配数据库(1998-2014年)
  • Letter Combination of a Phone Number
  • Redis原理之集群
  • windows内核研究(驱动开发之内核编程)
  • Qt控件实战详解:深入掌握输入输出与数据展示
  • Python MCP与Excel增强智能:构建下一代数据处理和自动化解决方案
  • SpringBoot 3.0 挥别 spring.factories,拥抱云原生新纪元
  • 人该怎样活着呢?55
  • 【RK3576】Android 14 驱动开发实战指南
  • uview-ui使用u-icon文字图标展示
  • 报错:升级gcc,centos