这道题的边界是dp(T,N)=0,状态dp(i,j)表示在时间i、第j个车站最少等待时间,有三个决策:1、等1分钟 2、如果有向左的车,向左 3、若果有向右的车,向右 转移方程就是dp(i,j)=min(dp(i+1,j),dp(i+t[j],j+1),dp(i+t[j-1],j-1))
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=1<<30;
const int maxn=200+5;
int dp[maxn][55];
int time[55],t[55];
int has[12600][55][2]; //has train
int main(){
int N,T,M1,M2;
int kase=0;
while(scanf("%d",&N)==1&&N){
scanf("%d",&T);
time[1]=0;
for(int i=2;i<=N;++i){
scanf("%d",&t[i]);
time[i]=time[i-1]+t[i];
}
memset(has,0,sizeof(has));
scanf("%d",&M1);
for(int i=1;i<=M1;++i){ //right
int r;
scanf("%d",&r);
for(int j=1;j<=N;++j){
has[r+time[j]][j][0]=1;
}
}
scanf("%d",&M2);
for(int i=1;i<=M2;++i){
int l;
scanf("%d",&l);
for(int j=N;j>=1;--j){
has[l+time[N]-time[j]][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[i][j][0]&&i+t[j+1]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j+1]][j+1]);
if(j>1&&has[i][j][1]&&i+t[j]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j]][j-1]);
}
printf("Case Number %d: ",++kase);
if(dp[0][1]>=INF) printf("impossible\n");
else printf("%d\n",dp[0][1]);
}
return 0;
}
若有不当之处欢迎指出!
318

被折叠的 条评论
为什么被折叠?



