紫书第九章-----动态规划初步(例题9-1 A Spy in the Metro UVA - 1025 )

A Spy in the Metro UVA - 1025

本文参考刘汝佳《算法竞赛入门经典》(第2版)
* 动态规划的核心是状态和状态转移方程*

/*
【理解题意】
    注意本题要求的是最短的等待时间!就是在各个车站等待的时间之和的最小值!
    建议通过输入输出样例来更好的明白题意!要尽量多在车上待着,减少在车站等
    的时间,这样安全乎!并且要保证在T时刻(约会时间)到达终点。
【动态规划】
    要注意时间这个天然的顺序!她总是在均匀的不停的流淌着……
    状态:d(i,j)表示i时刻,在j车站至少要等待的时间
    状态转移:在某个车站,
    1)继续等待:d(i,j)=d(i+1,j)+1
    2)坐左边来的车:d(i,j)=min{d(i+t[j],j+1) | j<n,i+t[j]<=T}
    3)坐右边来的车:d(i,j)=min{d(i+t[j-1],j-1) | j>1,i+t[j-1]<=T}
*/

#include<iostream>
#include<cstring>
using namespace std;

const int INF=200;//题目给出的T最大值是200,大于200不可能约会成功

int N,T,t[100],M1,d_L[100],M2,d_R[100];
int dp[300][100];
int kase=0;//打印要求打印编号
//has_train[300][100][0],has_train[300][100][1]分别标记左边和右边在i时刻,j车站是否有车
bool has_train[300][100][2];

int main()
{
    while(cin>>N && N){
        memset(has_train,false,sizeof(has_train));
        cin>>T;
        for(int i=1;i<N;i++){
            cin>>t[i];
        }
        cin>>M1;
        for(int i=0;i<M1;i++){
            cin>>d_L[i];
            int time=d_L[i];
            has_train[time][1][0]=true;
            for(int j=1;j<N;j++){
                time+=t[j];

                has_train[time][j+1][0]=true;
            }
        }
        cin>>M2;
        for(int i=0;i<M2;i++){
            cin>>d_R[i];
            int time=d_R[i];
            has_train[time][N][1]=true;
            for(int j=N;j>1;j--){
                time+=t[j-1];
                has_train[time][j-1][1]=true;
            }
        }



        //这里只初始化最后一行,从后向前递推即可
        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(i+t[j]<=T && j<N && has_train[i][j][0]){
                    dp[i][j]=min(dp[i][j],dp[i+t[j]][j+1]);
                }
                if(i+t[j-1]<=T && j>1 && has_train[i][j][1]){
                    dp[i][j]=min(dp[i][j],dp[i+t[j-1]][j-1]);
                }
            }
        }
        cout<<"Case Number "<<++kase<<": ";

        if(dp[0][1]>=INF){
            cout<<"impossible"<<endl;
        }else{
            cout<<dp[0][1]<<endl;
        }
    }
    return 0;
}

【本题注意】
要注意开数组开的稍微大一点,如果开的稍微小一点的话,可能过不了!!!

猜你喜欢

转载自blog.csdn.net/ccnuacmhdu/article/details/81169180