分析:时间是单向流逝的,是一个天然的“序"。影响到决策的只有当前时间和所处的车站,所以可以用d(i,j)表示时刻i,你在车站j,最少还需要等待多长时间。边界条件是d(T,n)=0,其它d(T,i)为正无穷。有如下3种决策。
决策1:等1分钟。
决策2:搭乘往右开的车(如果有)。
决策3:搭乘往左开的车(如果有)。
程序中用到 has_train 数组,其中 has_train[t][i][0]表示时刻 t,在车站 i 是否有往右开的车,has_train[t][i][1] 类似,不过记录的是往左开的火车。这个数组不难在输入时计算处理。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 55;
const int maxt = 210;
int interval[maxn];
int dp[maxt][maxn];
int has_train[maxt][maxn][2];
int main()
{
int n, T, kase = 0;
while(scanf("%d", &n), n) {
memset(has_train, 0, sizeof(has_train));
scanf("%d", &T);
for(int i=1; i<n; i++) scanf("%d", &interval[i]);
int m1, m2, mt, intv;
scanf("%d", &m1);
for(int i=0; i<m1; i++) {
scanf("%d", &mt);
has_train[mt][1][0] = 1;
intv = mt;
for(int j=1; j<n; j++) {
intv += interval[j];
has_train[intv][j+1][0] = 1;
}
}
scanf("%d", &m2);
for(int i=0; i<m2; i++) {
scanf("%d", &mt);
has_train[mt][n][1] = 1;
intv = mt;
for(int j=1; j<n; j++) {
intv += interval[n-j];
has_train[intv][n-j][1] = 1;
}
}
for(int i=1; i<n; i++) dp[T][i] = 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+interval[j]<=T)
dp[i][j] = min(dp[i][j], dp[i+interval[j]][j+1]);
if(j>1 && has_train[i][j][1] && i+interval[j-1]<=T)
dp[i][j] = min(dp[i][j], dp[i+interval[j-1]][j-1]);
}
printf("Case Number %d: ", ++kase);
if(dp[0][1] >= INF) printf("impossible\n");
else printf("%d\n", dp[0][1]);
}
return 0;
}