zoukankan      html  css  js  c++  java
  • 【最短路】Pod

    版权声明:本篇随笔版权归作者Etta(http://www.cnblogs.com/Etta/)所有,转载请保留原地址!

    现在让我们来对一个交通运输图进行研究,这可能是一个公交车的线路网、有轨电车线路网、地下铁的线路网或是其他的一个什么。这个图中的顶点(从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

    一、分析问题

           这是一个加限制条件的最短路问题。

    二、解决问题

           Spfa+等待时间的计算(详见代码)

    三、代码实现

      1 #include<cstdio>
      2 #include<queue>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 
      7 const int A = 4010*2,B = 1010,inf = 4e8;
      8 int n,m,k,st,en,gx,mx,sum;
      9 struct edge{
     10     int to,nxt,len,c,d;
     11 }e[A];
     12 int head[B],dis[B],ex[B];
     13 queue<int>q;
     14 
     15 void build(int f,int t,int l,int k,int c)
     16 {
     17     ++sum;
     18     e[sum].nxt=head[f];
     19     head[f]=sum;
     20     e[sum].to=t;
     21     e[sum].len=l;
     22     e[sum].d=k;
     23     e[sum].c=c;
     24 }
     25 
     26 void init()
     27 {
     28     int s2,c2,sum=0,sum1=0,d[B],s[B];
     29     scanf("%d%d%d%d%d%d",&n,&k,&st,&en,&gx,&mx);
     30     for(int i=1;i<=k;++i)
     31     {
     32         sum=0;
     33         sum1=0;
     34         scanf("%d%d",&s2,&c2);
     35         for(int j=1;j<=s2;++j)scanf("%d",&s[j]);
     36         for(int j=1;j<s2;++j)scanf("%d",&d[j]),sum+=d[j];
     37         for(int j=2;j<=s2;++j)
     38         {
     39             build(s[j-1],s[j],d[j-1],sum1,c2);
     40             sum-=d[j-1];
     41             sum1+=d[j-1];
     42             build(s[j],s[j-1],d[j-1],sum,c2);
     43         }
     44     }
     45 }
     46 
     47 
     48 void calc(int x,int y)//计算等待时间w
     49 {
     50     int w=e[y].d;//此时w是车辆到达的时刻(时间点)
     51     if(dis[x]<w)//车辆仍未到达,找在这之后的车
     52     {
     53         while(w-e[y].c>=dis[x])
     54             w-=e[y].c;
     55         w-=dis[x];
     56     }
     57     else//车辆已走,找在这之前的车
     58     {
     59         w=dis[x];
     60         while(w>e[y].d)
     61             w-=e[y].c;
     62         w=e[y].d-w;
     63     }
     64     if(dis[e[y].to]>dis[x]+e[y].len+w)
     65     {
     66         dis[e[y].to]=dis[x]+e[y].len+w;
     67         if(!ex[e[y].to])
     68         {
     69             ex[e[y].to]=1;
     70             q.push(e[y].to);
     71         }
     72     }
     73 }
     74 
     75 void SPFA()
     76 {
     77     for(int i=1;i<=n;++i)dis[i]=inf;
     78     dis[st]=mx;
     79     q.push(st);
     80     while(!q.empty())
     81     {
     82         int t=q.front();
     83         ex[t]=0;
     84         q.pop();
     85         for(int i=head[t];i;i=e[i].nxt)
     86             calc(t,i);
     87     }
     88 }
     89 
     90 void print()
     91 {
     92     int h,m;
     93     h=gx;
     94     m=dis[en];
     95     if(m>59)
     96     {
     97         h+=(m/60);
     98         m%=60;
     99     }
    100     h%=24;
    101     printf("%d %d
    ",h,m);
    102 }
    103 
    104 int main()
    105 {
    106     init();
    107     SPFA();
    108     print();
    109     return 0;
    110 }
  • 相关阅读:
    视图与URL配置--Hello world
    初始Django
    Django 学习之前提
    MySQL--解决中文乱码
    第二课时之c#语言基础
    第一课时之c#程序设计概述
    hdu--1029--思维题
    hdu--1028--dp||递推||母函数
    hdu--1026--bfs&&优先队列&&打印路径
    hdu--1027-next_permutation||dfs
  • 原文地址:https://www.cnblogs.com/Etta/p/6363418.html
Copyright © 2011-2022 走看看