uva A Spy in the Metro(洛谷 P2583 地铁间谍)

A Spy in the Metro

Secret agent Maria was sent to Algorithms City to carry out an especially dangerous mission. After several thrilling events we nd her in the rst station of Algorithms City Metro, examining the time table. The Algorithms City Metro consists of a single line with trains running both ways, so its time table is not complicated.

Maria has an appointment with a local spy at the last station of Algorithms City Metro. Maria knows that a powerful organization is after her. She also knows that while waiting at a station, she is at great risk of being caught. To hide in a running train is much safer, so she decides to stay in running trains as much as possible, even if this means traveling backward and forward. Maria needs to know a schedule with minimal waiting time at the stations that gets her to the last station in time for her appointment. You must write a program that nds the total waiting time in a best schedule for Maria.

The Algorithms City Metro system has N stations, consecutively numbered from 1 to N. Trains move in both directions: from the rst station to the last station and from the last station back to the rst station. The time required for a train to travel between two consecutive stations is xed since all trains move at the same speed. Trains make a very short stop at each station, which you can ignore for simplicity. Since she is a very fast agent, Maria can always change trains at a station even if the trains involved stop in that station at the same time.

                                                                                    

 

                                                                                    

                                                                   

Input

The input le contains several test cases. Each test case consists of seven lines with information as follows.

Line 1. The integer N (2 N 50), which is the number of stations.

Line 2. The integer T (0 T 200), which is the time of the appointment.

Line 3. N 1 integers: t1; t2; : : : ; tN 1 (1 ti 20), representing the travel times for the trains between two consecutive stations: t1 represents the travel time between the rst two stations, t2 the time between the second and the third station, and so on.

Line 4. The integer M1 (1 M1 50), representing the number of trains departing from the rst station.

Line 5. M1 integers: d1; d2; : : : ; dM1 (0 di 250 and di < di+1), representing the times at which trains depart from the rst station.

Line 6. The integer M2 (1 M2 50), representing the number of trains departing from the N-th station.

Line 7. M2 integers: e1; e2; : : : ; eM2 (0 ei 250 and ei < ei+1) representing the times at which trains depart from the N-th station.

The last case is followed by a line containing a single zero.

Output

For each test case, print a line containing the case number (starting with 1) and an integer representing the total waiting time in the stations for a best schedule, or the word `impossible' in case Maria is unable to make the appointment. Use the format of the sample output.

Sample Input

4

55

5 10 15

4

0 5 10 20

4

0 5 10 15

4

18

1 2 3

5

0 3 6 10 12

6

0 3 5 7 12 15

2

30

20

1

20

7

1 3 5 7 11 13 17

0

Sample Output

Case Number 1: 5

Case Number 2: 0

Case Number 3: impossible

.思路:时间是单向流逝的这是一个天然的“序”。影响决策的只有当前的时间和所在的车站。

这样我们就有了两种做法:

1.按时间倒序推:f[i][j]表示在时刻i,处在车站j,最少还需要多少时间。边界条件为f[T][n]=0,而其他的f[T][j]为正无穷,则有如下三种决策:

  ①:等一分钟,f[i][j]=f[i+1][j]+1。

  ②:如果有,则搭乘向右开的车,f[i][j]=min(f[i][j],f[i+t[j]][j+1])。

  ③:如果有,则搭乘向左开的车,f[i][j]=min(f[i][j],f[i+t[j-1]][j-1])。

2.按时间正序推:f[i][j]表示在时刻i,处在车站j,最少还需要多少时间。边界条件为f[0][1]=0,而其他的f[0][j]为正无穷,则有如下三种决策:

  ①:等一分钟,f[i][j]=f[i-1][j]+1。

  ②:如果有,则搭乘向右开的车,f[i][j]=min(f[i][j],f[i-t[j-1]][j-1])。

  ③:如果有,则搭乘向左开的车,f[i][j]=min(f[i][j],f[i-t[j]][j+1])。

时间倒序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int tot,n,T,t[800],M1,d1[800],M2,d2[800];
int f[2500][55],train[2500][55][2];
int main(){
    while(cin>>n&&n!=0){
        tot++;
        memset(f,0,sizeof(f));
        memset(train,0,sizeof(train));
        cin>>T;
        for(int i=1;i<n;i++)    cin>>t[i];
        cin>>M1;
        for(int i=1;i<=M1;i++)    cin>>d1[i];
        cin>>M2;
        for(int i=1;i<=M2;i++)    cin>>d2[i];
        for(int i=1;i<=M1;i++){
            int time=d1[i];
            for(int j=1;j<n;j++){
                train[time][j][0]=1;
                time+=t[j];
            }
        }
        for(int i=1;i<=M2;i++){
            int time=d2[i];
            for(int j=n;j>1;j--){
                train[time][j][1]=1;
                time+=t[j-1];
            }
        }
        for(int i=1;i<n;i++)    f[T][i]=123456789;
        f[T][n]=0;
        for(int i=T-1;i>=0;i--)
            for(int j=1;j<=n;j++){
                f[i][j]=f[i+1][j]+1;
                if(j<n&&train[i][j][0]&&i+t[j]<=T)
                    f[i][j]=min(f[i][j],f[i+t[j]][j+1]);
                if(j>1&&train[i][j][1]&&i+t[j-1]<=T)
                    f[i][j]=min(f[i][j],f[i+t[j-1]][j-1]);
            }
        cout<<"Case Number"<<" "<<tot<<": ";
        if(f[0][1]>=123456789)    cout<<"impossible"<<endl;
        else cout<<f[0][1]<<endl;
    }
}

时间正序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int tot,n,T,t[800],M1,d1[800],M2,d2[800];
int f[2500][55],train[2500][55][2];
int main(){
    while(cin>>n&&n!=0){
        tot++;
        memset(t,0,sizeof(t));
        memset(f,0x3f,sizeof(f));
        memset(train,0,sizeof(train));
        cin>>T;
        for(int i=1;i<n;i++)    cin>>t[i];
        cin>>M1;
        for(int i=1;i<=M1;i++)    cin>>d1[i];
        cin>>M2;
        for(int i=1;i<=M2;i++)    cin>>d2[i];
        for(int i=1;i<=M1;i++){
            int time=d1[i];
            for(int j=1;j<=n&&time<=T;j++){
                train[time][j][0]=1;
                time+=t[j];
            }
        }
        for(int i=1;i<=M2;i++){
            int time=d2[i];
            for(int j=n;j>=1&&time<=T;j--){
                train[time][j][1]=1;
                time+=t[j-1];
            }
        }
        f[0][1]=0;
        for(int i=1;i<=T;i++)
            for(int j=1;j<=n;j++){
                f[i][j]=min(f[i-1][j]+1,f[i][j]);
                if(train[i][j][0])
                    f[i][j]=min(f[i][j],f[i-t[j-1]][j-1]);
                if(train[i][j][1])
                    f[i][j]=min(f[i][j],f[i-t[j]][j+1]);
            }
        cout<<"Case Number"<<" "<<tot<<": ";
        if(f[T][n]<=T)    cout<<f[T][n]<<endl;
        else cout<<"impossible"<<endl;
    }
}

洛谷的相同的题目,或者说是题目翻译。

P2583 地铁间谍

题目描述

特工玛利亚被送到S市执行一个特别危险的任务。她需要利用地铁完成他的任务,S市的地铁只有一条线路运行,所以并不复杂。

玛利亚有一个任务,现在的时间为0,她要从第一个站出发,并在最后一站的间谍碰头。玛利亚知道有一个强大的组织正在追踪她,她知道如果一直呆在一个车站,她会有很大的被抓的风险,躲在运行的列车中是比较安全的。所以,她决定尽可能地呆在运行的列车中,她只能往前或往后坐车。

玛利亚为了能准时且安全的到达最后一个车站与对方碰头,需要知道在在车站最小等待时间总和的计划。你必须写一个程序,得到玛丽亚最短的等待时间。当然,到了终点站之后如果时间还没有到规定的时刻,她可以在车站里等着对方,只不过这个等待的时刻也是要算进去的。

这个城市有n个车站,编号是1-n,火车是这么移动的:从第一个车站开到最后一个车站。或者从最后一站发车然后开会来。火车在每特定两站之间行驶的时间是固定的,我们也可以忽略停车的时间,玛利亚的速度极快,所以他可以迅速上下车即使两辆车同时到站。

输入输出格式

输入格式:

 

输入文件包含多组数据,每组数据都由7行组成

第1行:一个正整数N(2<=N<=50)表示站的数量

第2行:一个正整数T(0<=T<=200)表示需要的碰头时间

第3行:1-(n-1)个正整数(0<ti<70)表示两站之间列车的通过时间

第4行:一个整数M1(1<=M1<=50)表示离开第一个车站的火车的数量

第5行:M1个正整数:d1,d2……dn,(0<=d<=250且di<di+1)表示每一列火车离开第一站的时间

第6行:一个正整数M2(1<=M2<=50)表示离开第N站的火车的数量

第7行:M2个正整数:e1,e2……eM2,(0<=e<=250且ei<ei+1)表示每一列火车离开第N站的时间

最后一行有一个整数0。

 

输出格式:

 

对于每个测试案例,打印一行“Case Number N: ”(N从1开始)和一个整数表示总等待的最短时间或者一个单词“impossible”如果玛丽亚不可能做到。按照样例的输出格式。

 

输入输出样例

输入样例#1:
4
55
5 10 15
4
0 5 10 20
4
0 5 10 15
4
18
1 2 3
5
0 3 6 10 12
6
0 3 5 7 12 15
2
30
20
1
20
7
1 3 5 7 11 13 17
0
输出样例#1:
Case Number 1: 5
Case Number 2: 0
Case Number 3: impossible

说明

第一组样例说明,她0分钟时上车,在3号站下车,立刻坐上(0分始发)15分开的车回去,到2号车站,立刻坐上(20分始发)25开的车到终点,50分到,还需要等待5分钟。

细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/7428964.html