题意:一个间谍要从第一个车站到第n个车站去会见另一个,在是期间有n个车站,有来回的车站,让你在时间T内时到达n,并且等车时间最短,输出最短等车时间。
思路:先用一个has_train[t][i][0]来表示在t时刻,在车站i,是否有往右开的车。同理,has_train[t][i][1]用来保存是否有往左开的车。
用d(i,j)表示时刻i,你在车站j,最少还需要等待多长时间。边界条件是d(T,n)=0,其他d(T,i)为正无穷。
每次有三种决策:
①:等一分钟。
②:搭成往右开的车(如果有)。
③:搭成往左开的车(如果有)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dis[55],cost[2][55],st[2][55],has_train[205][55][2],dp[205][55];
int main()
{
int n,T,M1,M2,i,j,Case=0;
while(scanf("%d",&n)&&n){
memset(dp,100,sizeof(dp));
memset(has_train,0,sizeof(has_train));
cost[0][1]=cost[1][n]=0;
Case++;
scanf("%d",&T);
dp[T][n]=0;
for(i=2;i<=n;i++){
scanf("%d",&dis[i]);
}
for(i=2;i<=n;i++){
cost[0][i]=cost[0][i-1]+dis[i];
}
for(i=n-1;i>=1;i--){
cost[1][i]=cost[1][i+1]+dis[i+1];
}
scanf("%d",&M1);
for(i=1;i<=M1;i++){
scanf("%d",&st[0][i]);
for(j=1;j<=n;j++){
if(cost[0][j]+st[0][i]>T) break;
has_train[cost[0][j]+st[0][i]][j][0]=1;
}
}
scanf("%d",&M2);
for(i=1;i<=M2;i++){
scanf("%d",&st[1][i]);
for(j=n;j>=1;j--){
if(cost[1][j]+st[1][i]>T) break;
has_train[cost[1][j]+st[1][i]][j][1]=1;
}
}
/* for(i=1;i<=n;i++){
for(j=0;j<=T;j++){
if(has_train[j][i][1])cout<<j<<' ';
}
cout<<endl;
} */
for(i=T-1;i>=0;i--){
for(j=1;j<=n;j++){
dp[i][j]=dp[i+1][j]+1;
if(j<n&&has_train[i][j][0]&&i+dis[j+1]<=T){
dp[i][j]=min(dp[i][j],dp[i+dis[j+1]][j+1]);
}
if(j>1&&has_train[i][j][1]&&i+dis[j]<=T){
dp[i][j]=min(dp[i][j],dp[i+dis[j]][j-1]);
}
}
}
printf("Case Number %d: ",Case);
if(dp[0][1]>1000000) printf("impossible\n");
else printf("%d\n",dp[0][1]);
}
return 0;
}