UVA - 1025 A Spy in the Metro(DP)

VJ原题

题意:

一个地铁有n个站,从1标号到n。有m1辆车从第一个站开往最后一个站,有m2辆车从末站开往第一个站。一个人在0时刻从1号站等车,打算在T时刻去到n号站见一个人。要求这个人等车的时间尽量的短,并且假设上下车和换车都不需要时间。求最短要等车多长时间。如果不可能到达终点站,那就输出“impossible”。

每个样例输入的数据意思为

                    一共有多少个站

T                     要在啥时候去见另一个人

t1 t2 .....tn-1  每个站之间需要走多长时间

m1                  有几个车是从1号站驶向n号站

t1 t2 ....tn       每个车都是几点发车

m2                  有几辆车从n号站驶向1号站

t1  t2 t3 .... tn 每个车的发车时间

解决过程:

整个过程影响我该怎么做的就是在那个车站和现在已经过了多少时间。设dp[i][j]表示第i时间在j车站最少要等多少时间。

于是有三种情况

1.等一分钟此时。(因为dp[i][j]表示的是还需要等多长时间,所以此刻比下一分钟要多等一分钟)

                         dp[i][j] = dp[i + 1][j] + 1;

2.坐上向右的车(如果在这个时间,这个站,有一辆向右走的车的话)

                         dp[i][j] = min(dp[i][j], dp[i + t[j]][j + 1]);

3.坐上向左的车(如果在这个时间,这个站 ,有一辆向左走的车的话)

                         dp[i][j] = min(dp[i][j], dp[i + t[j - 1]][j - 1]);

dp[T][n]为0,其他都为无穷大。

状态转移方程列出来时候,只剩下一个问题了,就是提前处理好,在什么时间,哪个站会有一辆行驶方向为何的列车。这个就尽量画个图看一看加减时间之后的时间应该赋给哪个站点。还有就是别忘了最开始的时候的标记。

剩下的就见代码吧~~

#include <iostream>
#include <cstdio>
#include <math.h>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <list>
#include <cstdlib>
#include <memory>
#include <cstring>
#include <sstream>
#include <vector>
using namespace std;

#define INF 0x3f3f3f3f
#define PI 3.141592653579
#define FRER() freopen("input.txt" , "r" , stdin);
#define FREW()  freopen("output.txt" , "w" , stdout);
#define  QIO std::ios::sync_with_stdio(false)
const double eps = 1e-8;
typedef long long ll;

const int maxn = 50+50;

int t[20+10];
bool train[200+50][maxn][2];
int dp[200+50][200+50];
int main()
{
    QIO;
    int cas = 1;
    int n;
    while(cin >> n && n)
    {
        memset(train , false , sizeof(train));
        memset(t , 0 , sizeof(t));
        memset(dp , false , sizeof(dp));
        int T;
        cin >> T;
        for(int i = 1 ; i < n; i++)
            cin >> t[i];
        int num;
        cin >> num;
        for(int i = 0 ; i < num ; i++)//go to the right
        {
            int time , currtime;
            cin >> time;
            currtime = time;
            train[currtime][1][0] = true;//标记最开始时候,列车还没有开始行使
            for(int j = 1 ; j < n ; j++)
            {
                currtime += t[j];
                if(currtime <= T)
                train[currtime][j+1][0] = true;
                else break;
            }
        }
        cin >> num;
        for(int i = 0 ; i < num ; i++)
        {
            int time , currtime = 0;
            cin >> time;
            currtime = time;
            train[currtime][n][1] = true;//标记最开始时候
            for(int j = n - 1 ;  j >= 1 ; j--)
            {
                currtime += t[j];
                if(currtime <= T)
                train[currtime][j][1] = true;
                else break;
            }
        }
        memset(dp , INF , sizeof(dp));
        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 (train[i][j][0] && i + t[j] <= T && j < n)
                    dp[i][j] = min(dp[i][j], dp[i + t[j]][j + 1]);
                if (train[i][j][1] && i + t[j - 1] <= T && j > 1)
                    dp[i][j] = min(dp[i][j], dp[i + t[j - 1]][j - 1]);
            }
        }
        printf("Case Number %d: ", cas++);
        if(dp[0][1] >= INF) printf("impossible\n");
        else printf("%d\n" , dp[0][1]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值