UVA1025题解——简单DP之多决策问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Q1410136042/article/details/80428370

题目链接:UVA-1025

题意:

给定n个车站,时间T,列车从车站i到车站i+1需要的时间t[i]。给定M1辆从车站1驶往车站n的列车发车时间,以及M2辆从车站n驶往车站1的列车发车时间。皮皮怪初始在车站1,要在T时刻到达车站n,问他至少要在车站等多久——车在车站停留时间忽略不计,并且假设皮皮怪特别敏捷,两辆车同时到车站他也能完成换乘,如果T时刻不可能在车站n就输出impossible。

分析:

这是一个很明显的多决策的问题,假设皮皮 i 时刻在车站 j(以dp[i][j]表示从现在开始他需要在车站等车的最少时间),那么他有三个决策:

(1)原地等一秒:dp[i][j] = dp[i+1][j]

(2)如果有向左的列车可搭乘:dp[i][j] = dp[i+t[i-1]][j-1]

(3)如果有向右的列车可搭乘:dp[i][j] = dp[i+t[i]][j+1]

我们需要做的就是在三个决策寻找最优的,也就是三个里最小的~

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<iomanip>
#include<algorithm>
#include<string>
#include<cstring>
#define LL long long
#define DEBUG printf("DEBUG\n")
#define FOR(i, s, n) for(int i = s; i < n; ++ i)
#define For(i, s, n) for(int i = s; i > n; -- i)

const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 1e5;

using namespace std;

int main()
{
    #ifdef AFei
    freopen("in.c", "r", stdin);
    #endif // AFei
    int n, T, _case = 1;
    int t[55];
    // n, T, t都是题目里的意思, _case是统计第几个case的
    bool hasTrain[210][55][2];
    // hasTrain[i][j][k]表示i时刻,j车站是否有火车,k为1表示向右,为0表示向左
    int dp[210][55];
    // dp[i][j]表示i时刻在j车站的情况下,还需要等待的时间
    while(scanf("%d", &n), n)
    {
        scanf("%d", &T);
        memset(hasTrain, 0, sizeof hasTrain);
        memset(dp, 0x3f, sizeof dp);
        dp[T][n] = 0;
        FOR(i, 1, n)    scanf("%d", &t[i]);
        int M, x;
        scanf("%d",  &M);
        FOR(i, 0, M)
        {
            scanf("%d", &x);
            if(x <= T)
            {
                hasTrain[x][1][1] = 1;
                FOR(j, 1, n-1)
                {
                    x += t[j];
                    if(x > T)
                        break;
                    hasTrain[x][j+1][1] = 1;
                    //处理向右的车到每一个车站的时间,不考虑最后一个车站
                }
            }
        }
        scanf("%d",  &M);
        FOR(i, 0, M)
        {
            scanf("%d", &x);
            if(x <= T)
            {
                hasTrain[x][n][0] = 1;
                For(j, n, 2)
                {
                    x += t[j-1];
                    if(x > T)
                        break;
                    hasTrain[x][j-1][0] = 1;
                    //处理向左的车到每一个车站的时间,不考虑第一个车站
                }
            }
        }
        For(i, T-1, -1)
        {
            For(j, n, 0)
            {
                int& tmp = dp[i][j];
                tmp = min(tmp, dp[i+1][j]) + 1;
                if(hasTrain[i][j][1] && i+t[j] <= T)//如果有向右的车
                    tmp = min(tmp, dp[i+t[j]][j+1]);
                if(hasTrain[i][j][0] && i+t[j-1] <= T)//如果有向左的车
                    tmp = min(tmp, dp[i+t[j-1]][j-1]);
            }
        }
        if(dp[0][1] > T)
            printf("Case Number %d: impossible\n", _case ++);
        else
            printf("Case Number %d: %d\n", _case ++, dp[0][1]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Q1410136042/article/details/80428370