题目背景

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 虫洞的更多相关文章

  1. 题解 P2620 虫洞

    总体思路:离散化 + 建图 + 单源最短路(看见人少蒟蒻才敢发题解QAQ) 需要注意的是: 考虑到w范围较大,而实际虫洞数量较小,就只记录虫洞的起点与终点来建图. 建图时,虫洞起点可以去重. 在建图时 ...

  2. hzwer模拟赛 虫洞

    [题目描述] N个虫洞,M条单向跃迁路径.从一个虫洞沿跃迁路径到另一个虫洞需要消耗一定量的燃料和1单位时间.虫洞有白洞和黑洞之分.设一条跃迁路径两端的虫洞质量差为delta. 1.从白洞跃迁到黑洞,消 ...

  3. BZOJ 1715: [Usaco2006 Dec]Wormholes 虫洞

    Description John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N ...

  4. BZOJ1715: [Usaco2006 Dec]Wormholes 虫洞

    1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 475  Solved: 263[Sub ...

  5. 1715: [Usaco2006 Dec]Wormholes 虫洞

    1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 501  Solved: 278[Sub ...

  6. [P2850][USACO06DEC]虫洞Wormholes (最短路)

    死活调不出来 后来是发现这题建边的原因…… 吐血.jpg 所谓的虫洞传说也就是负边了 然后这里打的spfa和原来的不一样 感觉hzwer大佬的spfa好强啊…… 也更易写一点 贴代码 #include ...

  7. bzoj2262: 平行宇宙与虫洞

    Description 量子力学指出,宇宙并非只有一种形态. 根据量子理论,一件事件发生之后可以产生不同的后果,而所有可能的后果都会形成自己的宇宙. 我们可以把一个宇宙看成一个时间轴,虫洞可以看成不同 ...

  8. SPFA穿越虫洞——负权回路得判断

    poj3259 题目大意:穿越虫洞可以回到过去(时间--)所以能不能让时间倒流呢,就是判断有没有负权回路这次尝试用SPFA算法,也可以复习一下链式前向星 准备工作,队列q,spfa算法得有点就在于这个 ...

  9. bzoj 1715: [Usaco2006 Dec]Wormholes 虫洞 -- spfa判断负环

    1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec  Memory Limit: 64 MB 注意第一次加边是双向边第二次是单向边,并且每次询问前数 ...

随机推荐

  1. Boyer-Moore字符串搜索(BM算法)的Python实现

    BM算法根据两个判据来进行字符串匹配,分别是“坏字符规则”和‘好后缀规则",其中好后缀规则可以单独使用,算法的图解可以参照下面这篇博文: https://www.cnblogs.com/wx ...

  2. Python爬虫系列(五):分析HTML结构

    今晚,被烦死了.9点多才下班,就想回来看书学习,结果被唠叨唠叨个小时,我不断喊不要和我聊天了,还反复说.我只想安安静静看看书,学习学习,全世界都不要打扰我 接着上一个讨论,我们今晚要分析HTML结构了 ...

  3. T - Nash Matrix CodeForces - 1316D

    题意: 输入n行数,没行由2*n个数,表示一个坐标(x,y). 如果x和y==-1表示从该点(i,j)出发,按照构造的前移动不会停下. 否则就要到点(x,y)处停下. 题解: 首先处理-1  枚举每个 ...

  4. 黑猫关键词URL采集工具 Pro v1.0

    功能介绍:黑猫关键词URL采集工具 Pro v1.0 批量关键词自动搜索采集 自动去除垃圾二级泛解析域名 可设置是否保存域名或者url 联系客服QQ:944520563

  5. JACTF Web部分

    掘安团队的题目 平台已不运营 Web签到 发现请求URL为flag.php,但是会跳转到404.php页面,抓包发现有302重定向,查看响应包,flag经过base64编码,解码即可 Tips: 重定 ...

  6. [php] 简单的实现一个错误接管类

    自己弄的一个错误接管类: <?php //---------------------------------- // Leephp 错误接管类 // 2017-07-06 // Pengchon ...

  7. HTML+CSS教程(四)选择器(id选择器,类选择器,标签选择器,子代选择器,后代选择器,组选择器,伪类选择器)/css引入页面的形式(行内样式、内嵌样式、外联样式)

    一.回顾内容 前端的三大组成(三大模块)    HTMl(超文本标记语言) 结构层    css(层叠样式表) 表现层:用来美化HTML结构    JS(Java script)(脚本语言) 行为层: ...

  8. Python神库分享之geoip2 IP定位库

    先安装这两个 pip install python-geoip-geolite2 -i https://pypi.douban.com/simple pip install geoip2 然后下载资源 ...

  9. 深入理解kestrel的应用

    1 前言 之所以写本文章,是因为在我停止维护多年前写的NetworkSocket组件两年多来,还是有一些开发者在关注这个项目,我希望有类似需求的开发者明白为什么要停止更新,可以使用什么更好的方式来替换 ...

  10. Java 添加、隐藏/显示、删除PDF图层

    本文介绍操作PDF图层的方法.可分为添加图层(包括添加线条.形状.字符串.图片等图层).隐藏或显示图层.删除图层等.具体可参考如下Java代码示例. 工具:Free Spire.PDF for Jav ...