A Spy in the Metro UVA - 1025

题意:有n(2<=n<=50)个车站,从左到右编号为1~n。有M1辆列车从第一站开始往右开,还有M2辆列车从第n站开始往左开。在时刻0某人从第一站出发,目的是在时刻T(0<=T<=200)会见车站n的一个间谍。在车站等车时容易被抓,所以这个人应尽量躲在开动的火车上,让在车站等待的时间应该尽量短。列车靠站停车时间忽略不计,并且这个人身手敏捷,即使两辆不同方向的列车在同一时间靠站,也能完成换乘。

输入第一行为n,第2行为T,第3行有n-1个整数ti(ti<=70),其中ti表示地铁从车站i到i+1的行驶时间(两个方向一样)。第4行为M1,(1<=M1<=50),即从第一站出发向右开的列车数目。第五行包含M1个整数dm(0<=dm<=250,di<d(i+1)),即各列车的出发时间。第6,7行描述从第n站出发向左开的列车,格式同第4,5行,输出仅包含一行,即最少等待时间。无解输出impossible。

思路:时间是单向流逝的,是一个天然的“序”。影响到决策的只有当前时间和所处的车站。所以可用d[i][j]表示时刻i,在车站j(序号为1~n)还需要等待多长时间,边界条件是d[T][n] = 0,其他d[T][i] = INF,有三种决策

1.等1分钟

2.搭乘向右开的车(如果有)

3.搭乘向左开的车(如果有);

has_train[i][j][0]表示时刻i在车站j是否有向右开的火车,has_train[i][j][1]表示时刻i在车站j是否有向左开的火车

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mod 1000000007;
using namespace std;
const int maxn = 52;
const int maxt = 202;
int n,T,l,r,x;
int t[maxn],dp[maxt][maxn];
int has_train[maxt][maxn][3];
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
int main()
{
    int kase = 1;
    while(scanf("%d",&n) && n)
    {
        scanf("%d",&T);
        memset(has_train,0,sizeof(has_train));
        for(int i = 1;i < n;i++) scanf("%d",&t[i]);
        scanf("%d",&l);
        for(int i = 1;i <= l;i++)
        {
            scanf("%d",&x);
            for(int j = 1;j < n;j++)
            {
                has_train[x][j][0] = 1;
                x += t[j];
            }
        }
        scanf("%d",&r);
        for(int i = 1;i <= r;i++)
        {
            scanf("%d",&x);
            for(int j = n;j > 1;j--)
            {
                has_train[x][j][1] = 1;
                x += t[j - 1];
            }
        }
        dp[T][n] = 0;
        for(int i = 1;i < n;i++) dp[T][i] = INF;
        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 && has_train[i][j][0] && i + t[j] <= T) dp[i][j] = min(dp[i][j],dp[i + t[j]][j + 1]);
                if(j > 1 && has_train[i][j][1] && i + t[j - 1] <= T) dp[i][j] = min(dp[i][j],dp[i + t[j - 1]][j - 1]);
            }
        }
        if(dp[0][1] >= INF) printf("Case Number %d: impossible\n",kase++);
        else printf("Case Number %d: %d\n",kase++,dp[0][1]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值