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 注意第一次加边是双向边第二次是单向边,并且每次询问前数 ...
随机推荐
- matplotlib TransformWrapper
2020-04-09 23:26:53 --Edit by yangray TransformWrapper 是Transform的子类, 支持在运行中替掉一个变换(可以是不同类型, 但维度必须相同) ...
- 来说说Java中String 类的那些事情
今天正好学校那边的任务不多,我就打算把Stirng 的有关知识点都总结在一起了,这样有利于知识的系统性,要不然学多了就会越来越杂,最主要的是总会忘记,记忆的时间太短了,通过这种方式,把它归纳在一起,写 ...
- mysql命令行参数 --- 这些参数不同于 mysqldump 后的 那些参数(下边文章开头有链接) :2种类型的参数 含义是不一样的
mysql命令行参数 --- 这些参数不同于 mysqldump 后的 那些参数 :2种类型的参数 含义是不一样的 一,mysql命令行参数 Usage: mysql [OPTIONS] [ ...
- 你知道python入门,是学到什么程度才算是吗?
1.入门的标准是什么? 这是很多初学者都关注的问题,但又是一个很难回答的问题,问题的核心是采取什么标准来衡量一个人是否已经入门. 以知识量的多少来衡量是不是可行呢?有些人走马观花一般学了很多pytho ...
- Python的深浅copy详解
Python的深浅copy详解 目录 Python的深浅copy详解 一.浅copy的原理 1.1 浅copy的定义 1.2 浅copy的方法 二.深copy的原理 2.1 深copy的定义 2.2 ...
- ajax ★ ★ ★ ★ ★
ajax 1 定义: 是创建交互式应用的网页交互技术 2 特点:无刷新.异步 3 中介数据类型: 1) XML - 可扩展的标记语言 ...
- 详解 Collection集合
(请关注 本人"集合总集篇"博文--<详解 集合框架>) 首先,本人来讲解下 Collection集合的继承体系: Collection集合 的继承体系: Collec ...
- Golang交付至Kubernetes
目录 0.前言 1.Go服务构建 1.1.制作Go服务镜像底包 1.2.制作slave基础镜像底包 1.2.1.Golang镜像 1.2.2.Docker镜像 2.创建golang流水线 3.流水线构 ...
- 用 Python 黄图批量鉴别审核
前言 最近写了一款微信小程序需要用到图片审核,人工审核是不可能的人工审核的太费精力了,所以我就写了一个多线程批量识别脚本来处理,主要是调用百度AI的接口,这里我是付费了也不贵审核一条1分钱不到,再说我 ...
- Java 多线程--ThreadLocal Timer ExecutorService
ThreadLocal /** * ThreadLocal:每个线程自身的存储本地.局部区域 * @author xzlf * */ public class ThreadLocalTest01 { ...