P2620 虫洞
题目背景
applepi 想进行宇宙旅行。当然,applepi 知道这是有可能的,因为applepi 的特殊能力能使他观测到宇宙中的虫洞。所谓虫洞就是一个在三维之外的维度打开的快捷通道,通过虫洞能够从一个地方瞬间移动到另外一个地方。
题目描述
为了简化问题,我们建立一个一维坐标系,地球的位置为\(0\),而applepi 的目的地的位置是一个正整数W。在每一个单位时间里,applepi可以向正方向移动不超过\(S\) 的一个整数。虫洞可以被表示为二元组\((B, E)\),即如果在某次移动之后applepi 在位置\(B\),那么applepi 就会被立刻传送到位置\(E\)。注意,applepi 在移动过程中如果经过位置\(B\),由于applepi 的速度极快是不会被传送的。而且,applepi 不能够向负方向移动,但是虫洞引起的除外。现在applepi 想请你帮助他计算一下他至少需要多少个单位时间才能够到达目的地。
输入格式
输入包含多组测试数据。
每组测试数据的第一行是三个正整数 \(W,S,P\),表示目的地位置,移动限制和虫洞的数目。之后 \(P\) 行,每行两个整数\(B\) 和\(E\),表示一个虫洞。
输入文件的最后一行是一个整数 \(0\),表示输入的结束。
输出格式
对于每组测试数据,在单独的一行内输出结果。
对于 \(100%\) 的数据,\(W\leq 10^9,2\leq S\leq 6,1\leq p\leq 40\),没有\(B = 0\) 或者\(B = W\) 的虫洞,输入数据保证目的地可达。
从简单图论那个题单点进来的,本来想A了以后就去做其它图论题单上的题,结果一天就调出来这一个。。。
首先,我觉得这不能是一个绿题,差不多要是蓝,虽然思路不难,但实现需要点功夫,所以,如果管理员看见希望可以考虑一下这个难度是否恰当当然也有可能是我太蒻
首先离散化:
言归正传,观察到,\(w\)特别大,但\(p,s\)很小,所以可以考虑从\(p,s\)入手开始乱搞
建图肯定不能一个数轴点对应一个节点了,考虑到起较大作用的点只有虫洞的两个端点
所以用一下离散化,只保留虫洞入口和出口,当然还要保留起点\((0)\)和终点\((w)\)这样点数是\(2p+2\),做完离散化后存在\(map\)数组中
关于离散化,通俗的讲,就是把没用的元素去掉,比如这个题两个虫洞的端点之间的那一堆点,就是没用的,不必保存下来,只保存有用的点(虫洞端点,起点终点),存下他们的坐标就行(存坐标的那个\(map\)数组的下标也就是建图时的节点编号)
然后还要排个序,方便下面操作
这玩意也听常用,更为深入的自己去百度吧,真的不难
然后想办法建图:
那么如何建图?
首先虫洞的起点和终点肯定是要连一条边权为\(0\)的边,至于如何通过点的组标确定其对应的节点编号,用二分实现,这是离散化的传统技能
因为我们走路肯定要借助虫洞,不用虫洞走的路就是:从一个虫洞的终点,走到另一个虫洞的起点
因此,我们可以枚举每两个有用的点,计算他们的的距离,如果第一个点的坐标是一个起点,就不计算直接返回无穷大
因为我们不能从一个起点开始走,走到那会接着被传送走,但是我们可以走到一个起点,走到那以后接着会从边长为\(0\)的虫洞边走到它对应的终点
对于如何判断一个点是否是起点,我用的map<int,int>
,对每个起点打上标记,题解区好多大佬用到是set
,不过本质一样
再考虑非虫洞边的边权咋计算:
设\(x,y\)分别是要计算的这条边的起点,终点
首先想到的是\(\lceil\dfrac{y-x}{s}\rceil\)
然而这样写完以后就会像我一样得到10分的好成绩
为什么?因为在\([x,y]\)中,还有一些点是虫洞入口,是不能踩的,一踩就被传送走了
例子楼上有大佬给出了
那我们可以考虑递归的计算(其实一开始想写成非递归,炸了,看来题解就写的递归
先贪心的每步都走\(s\),看看这样走第一个遇到的虫洞入口是哪个
至于如何实现,肯定就是枚举每个虫洞,都说了p很小
遇到了虫洞入口,就要一格一格往回退,直到遇见了不是虫洞入口的格子
那如果我又退回来起点,说明怎么走都白搭,走不了返回无穷大
没有退回到起点,假设退到\(y'\),那么从\(x\)到\(y'\)肯定就是\(\lceil\dfrac{y'-x}{s}\rceil\)了
那么\(y'\rightarrow y\)的费用,就可以递归计算了,递归到\(x=y\),费用肯定为\(0\),就返回
还有一个细节就是,当遇到了虫洞起点要开始往回退的时候,要判断一下当前这个入口是不是就是\(y\),如果是,那么说明已经走到了地方,就不退了
最后跑最短路
随便用什么算法跑个最短路就行,范围很小
如果你用dfs就当我没说
最后放上代码,可以从注释中体会一下我调代码时的心情
#include<cstdio>
#include<map>
#include<queue>
#include<cstring>
#include<cmath>
#include<algorithm>
#define reg register
#define EN std::puts("")
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=-1;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return x*y;
}
int n,p,s;
int map[106],tmp[106],tot;
std::map<int,int>start;
int dis[105][105];
int from[105],to[105];
inline int isstart(int x){//判断pos是不是一个起点
return start.find(x)==start.end()?0:1;
}
inline int find(int pos){//这个函数二分查找pos这个点对应的数组下标
reg int l=1,r=tot,mid,ret;
while(l<=r){
mid=(l+r)>>1;
if(map[mid]>=pos) ret=mid,r=mid-1;
else l=mid+1;
}
return ret;
}
inline int getdis(int x,int y){
if(x==y) return 0;
if(isstart(x)) return 0x3f3f3f3f;//x是个起点,不行
int yy=y;
for(reg int i=1;i<=p;i++)if(from[i]>x){
if(yy>from[i]&&(from[i]-x)%s==0) yy=from[i];
}
while(yy!=y&&isstart(yy)) yy--;//如果yy已经等于y了,就算是一个起点也不再退了
if(yy==x) return 0x3f3f3f3f;//退回了起点,永远到不了了qwq
return getdis(yy,y)+std::ceil((double)(yy-x)/s);
}
int main(){for(;;){
n=read();
if(!n) return 0;
s=read();p=read();
tot=0;start.clear();
tmp[++tot]=0;tmp[++tot]=n;
for(reg int i=1;i<=p;i++){
tmp[++tot]=from[i]=read();tmp[++tot]=to[i]=read();
start[from[i]]=1;
// std::printf("%d %d\n",start.find(from[i]),start.end());
}
//开始排序和去重
std::sort(tmp+1,tmp+1+tot);
reg int hq=tot;tot=0;
map[++tot]=tmp[1];
for(reg int i=2;i<=hq;i++)if(tmp[i]!=tmp[i-1])
map[++tot]=tmp[i];
//下面开始建边
std::memset(dis,0x3f,sizeof dis);
for(reg int i=1;i<=p;i++) dis[find(from[i])][find(to[i])]=0;
for(reg int i=1;i<=tot;i++)
for(reg int j=i+1;j<=tot;j++)
dis[i][j]=std::min(dis[i][j],getdis(map[i],map[j]));
//floyd
for(reg int k=1;k<=tot;k++)
for(reg int i=1;i<=tot;i++)
for(reg int j=1;j<=tot;j++) dis[i][j]=std::min(dis[i][j],dis[i][k]+dis[k][j]);
std::printf("%d\n",dis[1][tot]);
// for(reg int i=1;i<=tot;i++) std::printf("%d ",map[i]);std::puts("");
// for(reg int i=1;i<=p;i++) std::printf("%d %d\n",find(from[i]),find(to[i]));std::puts("");
// for(reg int i=1;i<=tot;i++){
// std::printf("%d: ",i);
// for(reg int j=1;j<=tot;j++) std::printf("%d ",dis[i][j]);
// std::puts("");
// }
}
}
P2620 虫洞的更多相关文章
- 题解 P2620 虫洞
总体思路:离散化 + 建图 + 单源最短路(看见人少蒟蒻才敢发题解QAQ) 需要注意的是: 考虑到w范围较大,而实际虫洞数量较小,就只记录虫洞的起点与终点来建图. 建图时,虫洞起点可以去重. 在建图时 ...
- hzwer模拟赛 虫洞
[题目描述] N个虫洞,M条单向跃迁路径.从一个虫洞沿跃迁路径到另一个虫洞需要消耗一定量的燃料和1单位时间.虫洞有白洞和黑洞之分.设一条跃迁路径两端的虫洞质量差为delta. 1.从白洞跃迁到黑洞,消 ...
- BZOJ 1715: [Usaco2006 Dec]Wormholes 虫洞
Description John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N ...
- BZOJ1715: [Usaco2006 Dec]Wormholes 虫洞
1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 475 Solved: 263[Sub ...
- 1715: [Usaco2006 Dec]Wormholes 虫洞
1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 501 Solved: 278[Sub ...
- [P2850][USACO06DEC]虫洞Wormholes (最短路)
死活调不出来 后来是发现这题建边的原因…… 吐血.jpg 所谓的虫洞传说也就是负边了 然后这里打的spfa和原来的不一样 感觉hzwer大佬的spfa好强啊…… 也更易写一点 贴代码 #include ...
- bzoj2262: 平行宇宙与虫洞
Description 量子力学指出,宇宙并非只有一种形态. 根据量子理论,一件事件发生之后可以产生不同的后果,而所有可能的后果都会形成自己的宇宙. 我们可以把一个宇宙看成一个时间轴,虫洞可以看成不同 ...
- SPFA穿越虫洞——负权回路得判断
poj3259 题目大意:穿越虫洞可以回到过去(时间--)所以能不能让时间倒流呢,就是判断有没有负权回路这次尝试用SPFA算法,也可以复习一下链式前向星 准备工作,队列q,spfa算法得有点就在于这个 ...
- bzoj 1715: [Usaco2006 Dec]Wormholes 虫洞 -- spfa判断负环
1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec Memory Limit: 64 MB 注意第一次加边是双向边第二次是单向边,并且每次询问前数 ...
随机推荐
- Android 图片裁剪库 uCrop
引语 晚上好,我是猫咪,我的公众号「程序媛猫咪」会推荐 GitHub 上好玩的项目,挖掘开源的价值,欢迎关注我. 现在 Android 开发,离不开图片,必然也需要图片裁剪功能,这个实现可以调用系统的 ...
- Google Adsense付款方式添加西联付款
本文已同步到专业技术网站 www.sufaith.com, 该网站专注于前后端开发技术与经验分享, 包含Web开发.Nodejs.Python.Linux.IT资讯等板块. Google Adsens ...
- 2020-3-30 20175110王礼博 Exp3 免杀原理与实践
目录 1.正确使用msf编码器 2.msfvenom生成如jar之类的其他文件 3.veil 4.加壳工具 5.使用C + shellcode编程 6.使用其他课堂未介绍方法 7.通过组合应用各种技术 ...
- Java虚拟机类装载的原理及实现(转)
Java虚拟机类装载的原理及实现(转) 一.引言 Java虚拟机(JVM)的类装载就是指将包含在类文件中的字节码装载到JVM中, 并使其成为JVM一部分的过程.JVM的类动态装载技术能够在运行时刻动态 ...
- Arthas-Java的线上问题定位工具
Arthas(阿尔萨斯) 能为你做什么? Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱. 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: 这个类从哪个 jar ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十三)之Strings
Immutable Strings Objects of the String class are immutable. If you examine the JDK documentation fo ...
- unity3d之简单动画
Unity3d中有两个关于动画的概念,Animation和Animator,看一下他们的创建和区别 1.创建一个物体后可以添加Animator和Animation组件如图所示 2.Animation和 ...
- tensorflow-参数、超参数、卷积核权值共享
根据网上查询到的说法,参数就是在卷积神经网络中可以被训练的参数,比如卷积核的权值和偏移等等,而超参数是一些预先设定好并且无法改变的,比如说是卷积核的个数等. 另外还有一个最最基础的概念,就是卷积核的权 ...
- 22-Java-Hibernate框架(二)
Hibernate的了解.Hibernate的搭建.Hibernate的基本使用流程等内容请阅读21-Java-Hibernate(一) 五.Hibernate的Query查询接口(重中之重) 1.H ...
- vue2.x学习笔记(十六)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12616543.html. 组件中的插槽 在2.6.0的版本中,vue为具名插槽和作用域插槽引入了一个新的统一的语法 ...