题意:
摘自lrj紫书——
某城市地铁是线性的,有n(2≤n≤50)个车站,从左到右编号1~n。有M1辆列车从第1站开始往右开,还有M2辆列车从第n站开始往左开。列车在相邻站台间所需的运行时间是固定的,因为所有列车的运行速度是相同的。在时刻0,Mario从第1站出发,目的在时刻T(0≤T≤200)会见车站n的一个间谍。在车站等车时容易被抓,所以她决定尽量躲在开动的火车上,让在车站等待的时间尽量短。列车靠站停车时间忽略不计,且Mario身手敏捷,即时两辆方向不同的列车在同一时间靠站,Mario也能完成换乘。
思路:
令 bool instationa[i][j] 表示i时刻是否有向左开的列车到达j站台,同理 instationb[i][j] 表示i时刻是否有向右开的列车到达j站台。
f[i][j]表示在i时刻到达j站台所需的最小等待时间,初始化f[i][j]=inf,其中f[0][1]=0。
转移方程:f[i][j]=min{f[i-d[j-1]][j-1] , f[i-d[j]][j+1] , f[i-1][j]+1}
注意:
要注意数组上下越界的问题,特别是处理instation时要注意不要处理那些超过数组容量的时间。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 50
#define maxt 200
#define inf 1000000
#define sta(a,b) instationa[a][b]
#define stb(a,b) instationb[a][b]
int n,t;
int m1,m2;
int d[maxn+5]= {0},dsum[maxn+5]= {0};
int a[maxn+5]= {0},b[maxn+5]= {0};
bool instationa[maxt+5][maxn+5]= {0};
bool instationb[maxt+5][maxn+5]= {0};
int f[maxt+5][maxn+5]= {0};
void readin() {
scanf("%d",&t);
for(int i=1; i<n; i++) scanf("%d",&d[i]);
scanf("%d",&m1);
for(int i=1; i<=m1; i++) {
scanf("%d",&a[i]);
}
scanf("%d",&m2);
for(int i=1; i<=m2; i++) {
scanf("%d",&b[i]);
}
}
void init() {
memset(instationa,0,sizeof(instationa));
memset(instationb,0,sizeof(instationb));
memset(dsum,0,sizeof(dsum));
for(int i=1; i<=n; i++) dsum[i]=dsum[i-1]+d[i-1];
for(int i=1; i<=m1; i++)
for(int j=1; j<=n; j++)
if(a[i]+dsum[j]<=t) instationa[a[i]+dsum[j]][j]=true;
for(int i=1; i<=m2; i++)
for(int j=1; j<=n; j++)
if(dsum[n]-dsum[j]+b[i]<=t) instationb[dsum[n]-dsum[j]+b[i]][j]=true;
for(int i=0; i<=maxt; i++)
for(int j=0; j<=maxn; j++)
f[i][j]=inf;
f[0][1]=0;
}
int dp() {
for(int i=1; i<=t; i++) {
for(int j=1; j<=n; j++) {
if(sta(i,j)&&i>=d[j-1]&&j!=1) f[i][j]=min(f[i][j],f[i-d[j-1]][j-1]);
if(stb(i,j)&&i>=d[j]&&j!=n) f[i][j]=min(f[i][j],f[i-d[j]][j+1]);
f[i][j]=min(f[i][j],f[i-1][j]+1);
}
}
return f[t][n];
}
int main() {
int T=0;
while(~scanf("%d",&n)&&n) {
readin();
init();
int ans=dp();
printf("Case Number %d: ",++T);
if(ans<inf) printf("%d\n",ans);
else printf("impossible\n");
}
return 0;
}