紫书例题 题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3466
是有向无环图的dp问题 dp[i][j]表示在i时刻j站台要等多少分钟
要先预处理在i时刻j站台是否有车,如果有就坐车,没有就等1分钟,然后继续决策。
判断是否有车用vis[i][j][k]表示,k表示向左或者向右,然后时间逆序dp,代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 1010
#define inf 0xfffffff
int dp[N][N],a[505],b[505],t[505];
int vis[N][N][2];
int main()
{
int n,m,j,i,T,m1,m2,kase=0;
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
memset(t,0,sizeof(t));
memset(b,0,sizeof(b));
if(n==0) break;
scanf("%d",&T);
for(i=1;i<=n-1;i++)
scanf("%d",&t[i]);
scanf("%d",&m1);
for(i=1;i<=m1;i++)
scanf("%d",&a[i]);
scanf("%d",&m2);
for(i=1;i<=m2;i++)
scanf("%d",&b[i]);
memset(dp,0,sizeof(dp));
for(i=1;i<=n-1;i++)
dp[T][i]=inf;
dp[T][n]=0;
memset(vis,0,sizeof(vis));
for(i=1;i<=m1;i++)
{
vis[a[i]][1][0]=1;
int tmp=a[i];
for(j=1;j<n;j++)
{
tmp+=t[j];
if(tmp<=T)
vis[tmp][j+1][0]=1;
else
break;
}
}
for(i=1;i<=m2;i++)
{
vis[b[i]][n][1]=1;
int tmp=b[i];
for(j=n-1;j>0;j--)
{
tmp+=t[j];
if(tmp<=T)
vis[tmp][j][1]=1;
else
break;
}
}
for(i=T-1;i>=0;i--)
for(j=1;j<=n;j++)
{
dp[i][j]=dp[i+1][j]+1;
if(j<n&&vis[i][j][0]&&i+t[j]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j]][j+1]);
if(j>1&&vis[i][j][1]&&i+t[j-1]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j-1]][j-1]);
}
printf("Case Number %d: ",++kase);
if(dp[0][1]>=inf) printf("impossible\n");
else printf("%d\n",dp[0][1]);
}
return 0;
}