题目背景

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. MySQL学习之路3-MySQL中常用数据类型

    MySQL中常用数据类型 字符型 存储字符型数据.例如姓名,地址,电话号码等.使用引号括起来,一般使用单引号. 常用类型: char(255) 定长字符串,最大长度255个字符. varchar(25 ...

  2. Win安装docker

    Windows Docker 安装 win7.win8 系统 win7.win8 等需要利用 docker toolbox 来安装,国内可以使用阿里云的镜像来下载,下载地址:http://mirror ...

  3. 如何配置多个Spring的xml配置文件(多模块配置)

    如何使用多个Spring的xml配置文件(多模块配置) (2009-08-22 13:42:43)   如何使用多个Spring的xml配置文件(多模块配置) 在用Struts Spring Hibe ...

  4. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十一)之Holding Your Objects

    To solve the general programming problem, you need to create any number of objects, anytime, anywher ...

  5. 【three.js 第一课】创建场景,显示几何体

    <!DOCTYPE html> <html> <head> <title>demo1</title> </head> <s ...

  6. L6循环神经网络

    循环神经网络 本节介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型.我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符.循环神经网络引入一个隐藏变量HHH,用HtH_{t}H ...

  7. G. 大树的水塘

    已知每块石头中的规格是1×1×1,水塘的长度为N,宽度为1,在第i位置,大树放了ai个石头 设大树建造的水塘蓄水量为V 请你求出在长度和宽度不变的情况下,建造一个蓄水量不小于V的水塘最多可以节约多少石 ...

  8. MRCTF Ezpop_Revenge小记

    前言 一道typecho1.2的反序列化,顺便记录一下踩的坑 www.zip获得源码,结构大致如下 flag.php需要ssrf,如果成功会写入session 拿到源码直接去网上先找了一下有没有现成的 ...

  9. [YII2] 视图层过滤客户恶意代码

    两种方式: 一种是吧html的恶意标签转译:(注意的就是命名空间) <?php use yii\helpers\Html; ?> <h1><?=Html::encode( ...

  10. 微信小程序画布(1)

    wxml: <view  catchtouchmove="preventTouchMove" wx:if="{{canvas_haoBao}}"> ...