A Spy in the Metro Uva-1025

题意:某城市的地铁是线性的,有n(2≤n≤50)个车站,从左到右编号为1-n。有M1辆列车从第1站开始往右开,还有M2辆列车从第n站开始往左开。在时刻0,Mario从第1站出发,目的是在时刻T(0≤T≤200)会见车站n的一个间谍。在车站等车时容易被抓,所以她决定尽量躲在开动的火车上,让在车站等待的总时间尽量短。列车靠站停车时间忽略不计,且Mario身手敏捷,即使两辆方向不同的列车在同一时间靠站,Mario也能完成换乘。
输入第1行为n,第2行为T,第3行有n-1个整数t1,t2,…,tn−1(1≤ti≤70),其中ti表示地铁从车站i到i+1的行驶时间(两个方向一样)。第4行为M1(1≤M1≤50),即从第1站出发向右开的列车数目。第5行包含M1个整数d1, d2,…, dM1(0≤di≤250,di<di+1),即各列车的出发时间。第6、7行描述从第n站出发向左开的列车,格式同第4、5行。输出仅包含一行,即最少等待时间。无解输出impossible。

思路:时间是顺序的,影响因素是某一时刻车在哪一个车站,所以建立dp[i][j]表示在第i秒内在第j个车站所等待的时间最少。train[i][j][0]表示在第i秒第j个车站可不可以向右走,可以为真,不可以为假,train[i][j][1]表示从n->1方向移动。在每一个车站有3种可能:1、原地等2、向右乘车(如果可以)3、向左乘车(如果可以)

#include<iostream>
#include<vector>
#include<algorithm>
#include <cstdio>
#include<cmath>
#include<set>
#include<queue>
#include<cstring>
#include<string>
#include<iomanip>
#define INF 0x3f3f3f
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=2100;
const double PI=acos(-1.0);
const int maxnn = 1e6;
int T,m1,m2;
int dp[maxn][maxn];//第i秒在第j个站用时最少
int train[maxn][maxn][2];//火车在第i秒可以向左或向右移动到第j个站
int t[maxn];//记录时间
int main()
{
    int n;
    int k=0;
    while(cin >> n && n != 0)
    {
        cin >> T;
        //memset(t,0,sizeof(t));
        t[0] = 0;
        for(int i = 1;i < n;i++)
        {
            cin >> t[i];
        }
        cin >> m1;
        memset(train,0,sizeof(train));//清空
        for(int i = 0;i < m1;i++)
        {
            int d;
            cin >> d;
            int s = d;
            for(int j = 0;j < n;j++)
            {
                s += t[j];
                if(s <= T)train[s][j+1][0] = 1;//在第s秒向右到达第j+1个站,因为j是从0开始的
                else
                    break;//如果超过T说明不能到达
            }
        }
        cin >> m2;
        for(int i = 0;i < m2;i++)
        {
            int d;
            cin >> d;
            train[d][n][1] = 1;
            int s = d;
            for(int j = n-1;j > 1 ;j--)
            {
                s += t[j];
                if(s <= T)train[s][j][1] = 1;
                else
                    break;
            }
        }
        for(int i = 1;i < n;i++)dp[T][i] = INF;
        dp[T][n] = 0;
        for(int i = T-1;i >= 0;i--)
        {
            for(int j = 1;j <= n;j++)
            {
                dp[i][j] = dp[i+1][j] + 1;
                if(j < n && train[i][j][0] && i + t[j] <= T)//如果向右走可以而且时间不超过T
                    dp[i][j] = min(dp[i][j],dp[i+t[j]][j+1]);//移动到下一个站(右),同时时间加上相应的t[j]
                if(j > 1 && train[i][j][1] && i + t[j-1] <= T)//如果向左走可以而且时间不超过T
                    dp[i][j] = min(dp[i][j],dp[i+t[j-1]][j-1]);//移动到下一个站(左),同时时间加上相应的t[j-1]
            }
        }
        if(dp[0][1] >= INF) printf("Case Number %d: impossible ", ++k);
        else printf("Case Number %d: %d ", ++k, dp[0][1]);//输出在第0秒时第一个站等待最少的时间
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kayiko/p/10798039.html