A Spy in the Metro UVA - 1025

题面:https://vjudge.net/problem/UVA-1025

思路:

紫书上的dp入门题,蒟蒻看了好久才看明白,下面就是思路。

首先要用一个三维数组has_train[i][j][k]表示在i时刻第j个站台是否有从左到右或从右到左的车(k = 0为从左到右,k = 1为从右到左)。

决策一共有3

决策1:在站台等一分钟。

决策2:搭乘向右开的车(如果有)

决策3:搭乘向左开的车(如果有)

建立dp数组dp[i][j]

首先是逆向递推,这也是lrj的思路。

此时dp[i][j]的定义是在i时刻,从j站台到n站台的最小停留时间。

从上面的三个决策,我们就可以得到递推式

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

因为决策23都是需要条件转移的,所以在转移时要加入判断条件,详细细节可以看下面代码。

初始化dp[T][n] = 0,最后答案是dp[0][1]

然后这道题还可以正向推

这个时候dp[i][j]的含义就是i时刻从1站台到j站台的最小停留时间

转移方程也对应发生了变化

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

要注意我们转移的方向变了所以判断决策23的条件也就变了。

初始化为dp[0][1] = 0,答案是dp[T][N]

代码1

 

#include <bits/stdc++.h>
using namespace std;
int dp[300][100];//时间为i时在j站台到n站台所花费的时间。
const int INF  = 0x3f3f3f3f;
bool has_train[300][100][2];//dp[i][j][0],mean there is a train which from left to right in j in i time
                            //dp[i][j][1],mean there is a train which from right to left in j in i time
int t[100];
int d1[100],d2[100];
int main()
{
    int N,T,M1,M2;
    int ca =1;
    while(scanf("%d",&N)&&N)
    {
        scanf("%d",&T);
        for(int i = 1;i<N;++i)
            scanf("%d",&t[i]);
        scanf("%d",&M1);
        for(int i = 1;i<=M1;++i)
            scanf("%d",&d1[i]);
        scanf("%d",&M2);
        for(int i =1;i<=M2;++i)
            scanf("%d",&d2[i]);
        memset(has_train,false,sizeof(has_train));
        for(int i = 1;i<=N;++i)
            dp[T][i] =INF;
        dp[T][N] = 0;
        for(int i =1;i<=M1;++i)
        {
            int x = d1[i];
            for(int j = 1;j<=N;++j)
            {
                if(x>T)
                    break;
                has_train[x][j][0] = true;
                x+=t[j];
            }
        }
        for(int i =1;i<=M2;++i)
        {
            int x = d2[i];
            for(int j =N;j>=1;--j)
            {
                if(x>T)
                    break;
                has_train[x][j][1] = true;
                x+=t[j-1];
            }
        }
        for(int i = T-1;i>=0;--i)
        {
            for(int j = 1;j<=N;++j)
            {
                 dp[i][j] = dp[i+1][j]+1;//决策1
                 if(j>1&&has_train[i][j][1]&&i+t[j-1]<=T)//决策3
                 {
                     dp[i][j] = min(dp[i][j],dp[i+t[j-1]][j-1]);
                 }
                 if(j<N&&has_train[i][j][0]&&i+t[j]<=T)//决策2
                    dp[i][j] = min(dp[i][j],dp[i+t[j]][j+1]);
            }
//            cout << i << ": ";
//            for(int j =1 ;j<=N;++j)
//                cout << dp[i][j] << " ";
//            cout << "\n";
        }
        printf("Case Number %d: ",ca++);
        if(dp[0][1]>=INF)
            printf("impossible\n");
        else
            printf("%d\n",dp[0][1]);
    }
    return 0;
}

 

代码2

#include <bits/stdc++.h>
using namespace std;
int dp[300][100];//时间为i时在1站台到j站台所花费的时间。
const int INF  = 0x3f3f3f3f;
bool has_train[300][100][2];
int t[100];
int d1[100],d2[100];
int main()
{
    int N,T,M1,M2;
    int ca =1;
    while(scanf("%d",&N)&&N)
    {
        scanf("%d",&T);
        for(int i = 1;i<N;++i)
            scanf("%d",&t[i]);
        scanf("%d",&M1);
        for(int i = 1;i<=M1;++i)
            scanf("%d",&d1[i]);
        scanf("%d",&M2);
        for(int i =1;i<=M2;++i)
            scanf("%d",&d2[i]);
        memset(has_train,false,sizeof(has_train));
        for(int i = 1;i<=N;++i)
            dp[0][i] =INF;
        dp[0][1] = 0;
        for(int i =1;i<=M1;++i)
        {
            int x = d1[i];
            for(int j = 1;j<=N;++j)
            {
                if(x>T)
                    break;
                has_train[x][j][0] = true;
                x+=t[j];
            }
        }
        for(int i =1;i<=M2;++i)
        {
            int x = d2[i];
            for(int j =N;j>=1;--j)
            {
                if(x>T)
                    break;
                has_train[x][j][1] = true;
                x+=t[j-1];
            }
        }
        for(int i = 1;i<=T;++i)
        {
            for(int j = 1;j<=N;++j)
            {
                 dp[i][j] = dp[i-1][j]+1;//决策1
                 if(j<N&&has_train[i][j][1]&&i-t[j]>=0)//决策3
                 {
                     dp[i][j] = min(dp[i][j],dp[i-t[j]][j+1]);
                 }
                 if(j>1&&has_train[i][j][0]&&i-t[j-1]>=0)//决策2
                    dp[i][j] = min(dp[i][j],dp[i-t[j-1]][j-1]);
            }
//            cout << i << ": ";
//            for(int j =1 ;j<=N;++j)
//                cout << dp[i][j] << " ";
//            cout << "\n";
        }
        printf("Case Number %d: ",ca++);
        if(dp[T][N]>=INF)
            printf("impossible\n");
        else
            printf("%d\n",dp[T][N]);
    }
    return 0;
}

 

 

posted @ 2020-02-09 14:25  浅花迷人  阅读(355)  评论(12编辑  收藏  举报