1. 程式人生 > >A Spy in the Metro(DP)

A Spy in the Metro(DP)

【題意】
       某城市裡的地鐵是線性的,有n個車站(2<=n<=50),有M1輛列車從第1站從左往右開,有M2輛列車從第n站從右往左開,在0時刻間諜從第一站出發,目的是要在時刻T(0<=T<=200)與另一個人在第n個車站碰頭,在車站等車時容易被抓,所以間諜要儘量躲在開動的火車上,從而讓他在車站的等待時間儘可能短。停車時間忽略不計,並且認為間諜可以瞬間完成換乘操作。

【輸入格式】
       多組輸入,第一行為n,第二行為T,第三行有n-1個整數,代表地鐵從第i站開到第i+1站所用時間,兩個方向上的時間是一樣的,第4行是M1,表示第1站出發向右開的火車數目,第五行有M1個整數代表每輛車的出發時間。6,7行同4,5行一樣描述的是從右往左開的列車資訊。

【輸出格式】
       有解時輸出最短時間,無解輸出”impossible”

【思路】
       把時刻和所處車站看成一種狀態,那麼假設dp[i][j]表示在時刻i,車站j,間諜的最小等待時間是多少。那麼接下來,間諜只能有這樣三種活動,(1).原地等待1s,等待時間+1. (2)坐車往左走. (3)坐車往右走,所以dp[i][j]一定是這三種情況的最小值,只需要需處理出每個車站在某個時刻有沒有向左開和向右開的火車之後就可以計算遞推dp[i][j]了,初始化dp[T][1]~dp[T][n-1]為無窮大,dp[T][n]=0

#include<bits/stdc++.h>
using namespace std; const int inf = 2e9; const int maxt = 220; const int maxn = 60; int n, T, cnt, kase = 0; int t[maxn]; bool hasTrain[maxt][maxn][2]; int dp[maxt][maxn]; void d() { for (int i = 0; i <= T; ++i) { for (int j = 1; j <= n; ++j) dp[i][j] = inf; } dp[T][n] = 0; for
(int i = T - 1; i >= 0; --i) { for (int j = 1; j <= n; ++j) { dp[i][j] = min(dp[i][j], dp[i + 1][j] + 1); if (j > 1 && hasTrain[i][j][0] && i + t[j - 1] <= T) { dp[i][j] = min(dp[i][j], dp[i + t[j - 1]][j - 1]); } if (j < n && hasTrain[i][j][1] && i + t[j] <= T) { dp[i][j] = min(dp[i][j], dp[i + t[j]][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]); } int main() { while (scanf("%d", &n) == 1 && n) { scanf("%d", &T); for (int i = 1; i < n; ++i) scanf("%d", &t[i]); memset(hasTrain, 0, sizeof(hasTrain)); scanf("%d", &cnt); for (int i = 1; i <= cnt; ++i) { int start; scanf("%d", &start); for (int j = 1; j <= n; ++j) { hasTrain[start][j][1] = true;//1向右 start += t[j]; if (start >= T) break; } } scanf("%d", &cnt); for (int i = 1; i <= cnt; ++i) { int start; scanf("%d", &start); for (int j = n; j >= 1; --j) { hasTrain[start][j][0] = true;//0向左 start += t[j - 1]; if (start >= T) break; } } d(); } return 0; }