旅行(最短路)
2016-08-23 20:22
369 查看
旅行
POD
现在让我们来对一个交通运输图进行研究,这可能是一个公交车的线路网、有轨电车线路网、地下铁的线路网或是其他的一个什么。这个图中的顶点(从1到n标号)为车站,边(pi ,pj)(这里pi ¹ pj)表示在顶点pi和顶点pj间存在一条直接连接两点的路(1
£ pi, pj £ n)。在图中有从1到k编号的k条运输路线,第l号路线是用一个车站序列pl,1,
pl,2, …, pl,sl来描述的,它们为使用这个线路的车辆将依次经过的车站。并且我们给出它们之间的距离rl,1, rl,2, …, rl,sl-1,其中rl,i表示从车站pl,i到车站pl,i+1所需的时间。对于一条线路来说,它上面所有的车站都是不相同的(也就是说,若i ¹ j,则pl,i ¹ pl,j)。且线路l将以频率cl运行。这里cl为集合{6,
10, 12, 15, 20, 30 ,60}中的一个数,它表示每个小时的0, cl, 2cl, …, 60分钟的时候在路线l上的将有两辆车同时从车站pl,1和pl,sl出发相对着行进。
在这样一个运输网络中,我们想从其中的一个车站x出发用尽可能少的时间到达车站y。这里我们假设最少的时间不会超过24个小时,且在中途换车的时候的时间不计。
示例:
在下图中你可以看到一个具有六个车站和两条路线的运输网络。路线一上的车站序列为1、3、4、6,路线二上的车站序列为2、4、3、5,且两条路线的频率分别为c1=15和c2=20。车辆在各车站间移动时的耗费都分别用1和2的下标标在了图上。
现在我们假设在23点30分的时候我们在车站5想要到车站6去。我们必须等上10分钟才可以搭上一辆路线2的车离开。然后我们就面临着两种选择:一种是在23点51分到车站3等上3分钟并改乘路线1的车于0点16分到达车站6;另一种是在0点8分到达车站4等上13分钟再换路线1的车于0点31分到达车站6。显然最早我们能在0点16分到达车站6。
任务:
请写一个程序:
从文本文件POD.IN中读入对该交通运输网的描述、起点和终点、还有出发的时间;
找出从起点到终点的最少时间;
把最找到达终点的时间输出到文本文件POD.OUT中。
输入格式:
在文本文件POD.IN的第一行包括六个用空格分开的整数,分别为:
n,1 <= n <= 1000,为车站的数目;
k,1 <= k <= 2000,为路线的数目;
x,1 <= x <= n,为起点的车站编号;
y,1 <= y <= n,为终点的车站编号;
gx,0 <= gx <= 23,为出发时间的小时数;
mx,0 <= mx <= 59,为出发时间的分钟数。
车站是从1到n编号的,运输路线是用1到k编号的。以下的3k行为对运输路线的描述。这些行中每3行构成一个对一条路线的描述,第k个三行的意义如下:
第一行包括两个用空格分开的整数,sl(2 <=sl<= n)为该路线上车站的数目,还有cl({6,
10, 12, 15, 20, 30, 60}中的一个元素),为该路线运行的频率;
第二行包括sl个用空格分开的不同的整数,为pl,1, pl,2, …,pl,sl(1<= pl,i<= n),即该路线上的车站;
第三行包括sl-1个整数rl,1, rl,2, …,rl,sl-1为在路线上相邻两个车站间移动所需的时间(1<= rl,i<= 240)。
在所有的运输路线上的总车站数不超过4000(也就是说s1 + s2 + … + sk <=4000)。
输出格式:
你的程序应该在文本文件POD.OUT中输出两个整数gy(0<=gy<= 23)和my(0<=
my<=59),表示到达y点时的小时数和分钟数。
样例:
输入(POD.IN):
6 2 5 6 23 30
4 15
1 3 4 6
9 12 10
4 20
5 3 4 2
11 17 11
输出(POD.OUT):
0 16
题解:最短路。
数组f[i][j]表示走j号线路到达i这个点所需要的最少的分钟数。为了便于计算直接把读入的mx作为初值即可。
然后更新的时候计算需要等的时间加入答案即可。
POD
现在让我们来对一个交通运输图进行研究,这可能是一个公交车的线路网、有轨电车线路网、地下铁的线路网或是其他的一个什么。这个图中的顶点(从1到n标号)为车站,边(pi ,pj)(这里pi ¹ pj)表示在顶点pi和顶点pj间存在一条直接连接两点的路(1
£ pi, pj £ n)。在图中有从1到k编号的k条运输路线,第l号路线是用一个车站序列pl,1,
pl,2, …, pl,sl来描述的,它们为使用这个线路的车辆将依次经过的车站。并且我们给出它们之间的距离rl,1, rl,2, …, rl,sl-1,其中rl,i表示从车站pl,i到车站pl,i+1所需的时间。对于一条线路来说,它上面所有的车站都是不相同的(也就是说,若i ¹ j,则pl,i ¹ pl,j)。且线路l将以频率cl运行。这里cl为集合{6,
10, 12, 15, 20, 30 ,60}中的一个数,它表示每个小时的0, cl, 2cl, …, 60分钟的时候在路线l上的将有两辆车同时从车站pl,1和pl,sl出发相对着行进。
在这样一个运输网络中,我们想从其中的一个车站x出发用尽可能少的时间到达车站y。这里我们假设最少的时间不会超过24个小时,且在中途换车的时候的时间不计。
示例:
在下图中你可以看到一个具有六个车站和两条路线的运输网络。路线一上的车站序列为1、3、4、6,路线二上的车站序列为2、4、3、5,且两条路线的频率分别为c1=15和c2=20。车辆在各车站间移动时的耗费都分别用1和2的下标标在了图上。
现在我们假设在23点30分的时候我们在车站5想要到车站6去。我们必须等上10分钟才可以搭上一辆路线2的车离开。然后我们就面临着两种选择:一种是在23点51分到车站3等上3分钟并改乘路线1的车于0点16分到达车站6;另一种是在0点8分到达车站4等上13分钟再换路线1的车于0点31分到达车站6。显然最早我们能在0点16分到达车站6。
任务:
请写一个程序:
从文本文件POD.IN中读入对该交通运输网的描述、起点和终点、还有出发的时间;
找出从起点到终点的最少时间;
把最找到达终点的时间输出到文本文件POD.OUT中。
输入格式:
在文本文件POD.IN的第一行包括六个用空格分开的整数,分别为:
n,1 <= n <= 1000,为车站的数目;
k,1 <= k <= 2000,为路线的数目;
x,1 <= x <= n,为起点的车站编号;
y,1 <= y <= n,为终点的车站编号;
gx,0 <= gx <= 23,为出发时间的小时数;
mx,0 <= mx <= 59,为出发时间的分钟数。
车站是从1到n编号的,运输路线是用1到k编号的。以下的3k行为对运输路线的描述。这些行中每3行构成一个对一条路线的描述,第k个三行的意义如下:
第一行包括两个用空格分开的整数,sl(2 <=sl<= n)为该路线上车站的数目,还有cl({6,
10, 12, 15, 20, 30, 60}中的一个元素),为该路线运行的频率;
第二行包括sl个用空格分开的不同的整数,为pl,1, pl,2, …,pl,sl(1<= pl,i<= n),即该路线上的车站;
第三行包括sl-1个整数rl,1, rl,2, …,rl,sl-1为在路线上相邻两个车站间移动所需的时间(1<= rl,i<= 240)。
在所有的运输路线上的总车站数不超过4000(也就是说s1 + s2 + … + sk <=4000)。
输出格式:
你的程序应该在文本文件POD.OUT中输出两个整数gy(0<=gy<= 23)和my(0<=
my<=59),表示到达y点时的小时数和分钟数。
样例:
输入(POD.IN):
6 2 5 6 23 30
4 15
1 3 4 6
9 12 10
4 20
5 3 4 2
11 17 11
输出(POD.OUT):
0 16
题解:最短路。
数组f[i][j]表示走j号线路到达i这个点所需要的最少的分钟数。为了便于计算直接把读入的mx作为初值即可。
然后更新的时候计算需要等的时间加入答案即可。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #define N 20003 using namespace std; int point ,next ,v ,c ,num ,pd ; int t ,s ,gx,mx,dis[2003][2003],can[2003][2003]; int n,m,start,end,f[2003][2003],tot,road ; struct data { int x,y; }; void add(int x,int y,int k,int b) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=k; num[tot]=b; pd[tot]=1; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=k; num[tot]=b; pd[tot]=0; } int calc1(int k,int mark,int l,int x) { int len=0; if (mark) len=dis[k][x]; else len=road[k]-dis[k][x]; int wer=l-len; while (wer>=60) wer-=60; while (wer<0) wer+=60; int wt=t[k]-(wer%t[k]); if (wt==t[k]) return 0; else return wt; } int bfs() { memset(f,127/3,sizeof(f)); data a; a.x=start; a.y=0; queue<data> p; p.push(a); f[start][0]=mx; can[start][0]=1; while (!p.empty()) { data a=p.front(); p.pop(); int now=a.x; for (int i=point[now];i;i=next[i]) { int t=calc1(num[i],pd[i],f[now][a.y],now); if (f[now][a.y]+t+c[i]<f[v[i]][num[i]]) { f[v[i]][num[i]]=f[now][a.y]+t+c[i]; if (!can[v[i]][num[i]]) { can[v[i]][num[i]]=1; data b; b.x=v[i]; b.y=num[i]; p.push(b); } } } can[now][a.y]=0; } int ans=1000000000; for (int i=0;i<=m;i++) ans=min(ans,f[end][i]); return ans; } int main() { freopen("pod.in","r",stdin); freopen("pod.out","w",stdout); scanf("%d%d%d%d%d%d",&n,&m,&start,&end,&gx,&mx); for (int i=1;i<=m;i++) { scanf("%d%d",&s[i],&t[i]); int p ,len ; for (int j=1;j<=s[i];j++) scanf("%d",&p[j]); for (int j=1;j<=s[i]-1;j++) scanf("%d",&len[j]),dis[i][p[j+1]]=dis[i][p[j]]+len[j]; for (int j=1;j<=s[i]-1;j++) add(p[j],p[j+1],len[j],i); road[i]=dis[i][p[s[i]]]; } int ans=bfs(); printf("%d %d\n",(gx+ans/60)%24,ans%60); }
相关文章推荐
- logback.xml常用配置详解<configuration> and <logger>
- C# 文件夹,文件操作
- UDP广播问题
- 图的深度遍历
- 求乘方取模(快速幂+慢速乘法模板)
- Java静态分派与动态分派
- 线性同余方程及例题 codeforces 710D
- 4000 java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoa
- Android学习笔记--3.Intent的使用
- java虚拟机垃圾回收
- & |运算小记
- C++学习笔记之——map set 与 opencv中的数据结构 如 point 等不兼容
- 关于oracle with as用法
- uvalive 6693 - Flow Game - BFS
- Qt 菜鸟的坑 QAbstractSocket::isValid()
- Android中所有API和对应权限的数据结构构建
- refresh的停车场
- 简单方法实现Android阅读器分页
- Winform部分控件使用
- 线程池 队列生产者消费者模型实现