题意:有n个车站,起点车站和终点车站都有k辆列车分别在不同时刻出发,问从起点走的人在指定时刻到终点,最少要等多长时间。
分析:拿到题目,感觉很复杂,看了作者的分析,才明白怎么dp,看似不好dp,实际只要找到以时间为关键点,等待时间为dp对象就好做了,从t时刻终点开始,每次都有等1单位和乘向左或向右列车的方案。如果乘列车那么等待时间就不会变。
#include<iostream>
#include<string.h>
#include<sstream>
#include<set>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<math.h>
using namespace std;
const int maxn=50+5;
const int maxt = 200 + 5;
const int INF = 10000000000;
int t[maxn], has_train[maxt][maxn][2];
int dp[maxt][maxn];
int main()
{
int kase=0,n,T;
while (cin >> n>>T&&n) {
int M1, M2, d;
for (int i = 1; i < n; i++)cin >> t[i];
memset(has_train, 0, sizeof(has_train));
cin >> M1;
while (M1--) {
int d;
cin >> d;
for (int j = 1; j < n; j++) {
if (d <= T)has_train[d][j][0] = 1;
d += t[j];
}
}
cin >> M2;
while (M2--) {
int d;
cin >> d;
for (int j = n-1; j >0; j--) {
if (d <= T)has_train[d][j+1][1] = 1;
d += t[j];
}
}
for (int j = 1; j < n; j++)dp[T][j] = INF;
dp[T][n] = 0;
for (int i = T - 1; i >= 0; i--) {
for (int j = 1; j <= n; j++) {
dp[i][j] = dp[i + 1][j] + 1;
if (j < n&&has_train[i][j][0] && i + t[j] <= T) {//向右
dp[i][j] = min(dp[i][j], dp[i + t[j]][j + 1]);
}
if (j > 1 && has_train[i][j][1] && i + t[j - 1] <= T) {//向左
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\n";
else cout << dp[0][1]<< endl;
}
return 0;
}