#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500;
const int INF=0x3f3f3f3f;
int n,t;
int a[maxn];
int m1,m2;
int d[maxn],e[maxn];
int train[300][100][2];
int dp[maxn][maxn];
int main()
{
int kase=1;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
memset(train,0,sizeof(train));
memset(dp,0x3f,sizeof(dp));
scanf("%d",&t);
for(int i=1;i<=n-1;i++)
{
scanf("%d",&a[i]);
}
a[0]=0;
a[n]=0;
scanf("%d",&m1);
for(int i=0;i<m1;i++)
scanf("%d",&d[i]);
for(int i=0;i<m1;i++)//预处理向右的状态,visit[i][j][0]表示i时刻j车站是否有向右的车
{
train[d[i]][1][0]=1;
int temp=d[i];
for(int j=1;j<n;j++)
{
temp+=a[j];
if(temp<=t)
train[temp][j+1][0]=1;
else
break;
}
}
scanf("%d",&m2);
for(int i=0;i<m2;i++)
scanf("%d",&e[i]);
for(int i=0;i<m2;i++)
{
train[e[i]][n][1]=1;
int temp=e[i];
for(int j=n-1;j>=1;j--)
{
temp+=a[j];
if(temp<=t)
train[temp][j][1]=1;
else
break;
}
}
/*for(int k=0;k<=1;k++)
{
for(int i=0;i<=t;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",train[i][j][k]);
}
}
}*/
for(int i=1;i<=n-1;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&&train[i][j][0]&&i+a[j]<=t)
dp[i][j]=min(dp[i][j],dp[i+a[j]][j+1]);
if(j>1&&train[i][j][1]&&i+a[j-1]<=t)
dp[i][j]=min(dp[i][j],dp[i+a[j-1]][j-1]);
}
}
if(dp[0][1]>=INF)
printf("Case Number %d: impossible\n",kase++);
else
printf("Case Number %d: %d\n",kase++,dp[0][1]);
}
return 0;
}
又是这种两头跑的DP题目,申请了肯定有一个状态表示t时n站的然后用01表示左右方向跑的方法,dp代表的是在t时刻在j位置时能最终到达终点要求dp(t,n)期间,能所等待的最少的时间,然后确定了决策有三种,一种是在原地等待一秒,然后还有就是向左向右跑如果还有能跑的话。所以的等待时间都是在原地等待一秒所累加而产生的。
UVa 1025
最新推荐文章于 2020-07-30 20:57:25 发布