【题意】(小紫书)一个人从站台1出发,乘车要在时刻T到达站台n,为使在站台等车时间最短,她可以选择乘坐两个方向的列车,并在客车停靠站的时候换车。
【分析】每次停站下车时,她都有三种选择,1.原地不动 2.搭乘向右的车 3.搭乘向左的车。d[i][j]表示在站台i,时刻j的最小等待时间。
状态转移方程:
等待:dp[i][j]=dp[i][j+1]+1;
如果有向右的车: dp[i][j]=min(dp[i][j],dp[i+1][j+t[i]]);
如果有向左的车: dp[i][j]=min(dp[i][j],dp[i-1][j+t[i-1]]);
注意:
1.某时刻某车站是否有车,可以使用一个三维数组has_train来记录。
2.边界条件 dp[N][T]=0
【代码】
#include<cstdio> #include<cstring> #define min(a,b) (a)<(b)?(a):(b) const int maxn=250; const int INF=0xfffffff; int has_train[55][250][2]; int t[250]; int d[55]; int e[55]; int dp[50][200]; int main (void) { int N,T,total,M1,M2,c=0; while(scanf("%d",&N)==1&&N) { memset(has_train,0,sizeof(has_train)); scanf("%d",&T); for(int i=1;i<=N-1;i++) scanf("%d",&t[i]); scanf("%d",&M1); for(int i=1;i<=M1;i++) { scanf("%d",&d[i]); total=0; has_train[1][d[i]][0]=1; for(int j=1;j<=N-1;j++) { total+=t[j]; if(d[i]+total<=T) has_train[j+1][d[i]+total][0]=1; else break; } } scanf("%d",&M2); for(int i=1;i<=M2;i++) { scanf("%d",&e[i]); total=0; has_train[N][e[i]][1]=1; for(int j=N-1;j>=1;j--) { total+=t[j]; if(e[i]+total<=T) has_train[j][e[i]+total][1]=1; else break; } } for(int i=1;i<=N;i++) for(int j=0;j<=T;j++) dp[i][j]=INF; dp[N][T]=0; for(int j=T-1;j>=0;j--) { for(int i=1;i<=N;i++)//i车站j时刻 { dp[i][j]=dp[i][j+1]+1; if(j+t[i]<=T&&has_train[i][j][0]&&i<N) dp[i][j]=min(dp[i][j],dp[i+1][j+t[i]]); if(j+t[i-1]<=T&&has_train[i][j][1]&&i>1) dp[i][j]=min(dp[i][j],dp[i-1][j+t[i-1]]); } } if(dp[1][0]>=INF) printf("Case Number %d: impossible ",++c); else printf("Case Number %d: %d ",++c,dp[1][0]); } return 0; }