Uva 1025 - A Spy in the Metro(DP)
题目链接 https://vjudge.net/problem/UVA-1025
【题意】
某城市里的地铁是线性的,有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;
}