描述
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3466
某城市的地铁是线性的,有n个车站,有M1辆列车从左到右开,M2辆列车从右到左开.在0时刻,你在第一站,要在T时刻到达第n站,其间可以随意换车,要求在车站等待的时间最短.
分析
用dp[i][j]表示在i时刻,在第j站,要达到目的,需要等待多久.显然dp[T][n]=0,对于任意i!=n,dp[T][i]=INF,要求dp[0][1].那么转移方程:
dp[i][j]=1.dp[i+1][j]+1(在车站等一分钟).
2.dp[i+t[j]][j+1](如果有,乘坐向右的列车).
3.dp[i+t[j-1]][j-1](如果有,乘坐向左的列车).
#include <bits/stdc++.h>
using namespace std; const int maxn=+,maxt=+,INF=0x3fffffff;
int n,T,M1,M2,kase;
int t[maxn],dp[maxt][maxn];
bool has_train[maxt][maxn][]; void solve(){
for(int i=;i<=n;i++) dp[T][i]=INF;
dp[T][n]=;
for(int i=T-;i>=;i--)
for(int j=;j<=n;j++){
dp[i][j]=dp[i+][j]+;
if(j<n&&has_train[i][j][]&&i+t[j]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j]][j+]);
if(j>&&has_train[i][j][]&&i+t[j-]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j-]][j-]);
}
printf("Case Number %d: ",++kase);
if(dp[][]>=INF) puts("impossible");
else printf("%d\n",dp[][]);
}
void init(){
scanf("%d",&T);
for(int i=;i<n;i++){
scanf("%d",&t[i]);
}
memset(has_train,,sizeof has_train);
scanf("%d",&M1);
for(int i=;i<=M1;i++){
int d; scanf("%d",&d);
int station=;
while(d<=T&&station<n){
has_train[d][station][]=true;
d+=t[station++];
}
}
scanf("%d",&M2);
for(int i=;i<=M2;i++){
int d; scanf("%d",&d);
int station=n;
while(d<=T&&station>){
has_train[d][station][]=true;
d+=t[station-]; station--;
}
}
}
int main(){
while(scanf("%d",&n)&&n){
init();
solve();
}
return ;
}