版权声明: https://blog.csdn.net/a673953508/article/details/83411370
题解:
这道题目基本上是线性dp,,只需要在记率每个时刻,每个车站左边或者右边有木有车驶来,
一共有三种状态(等待,上左车,上右车),就可以判断下一状态需要等待的时间了,具体解法紫书上有说明
注意点:需要注意你保存每一站的时间的下标是怎样的,然后根据你的下标在你记录车辆的时候注意下标,dp的时候也要注意下标
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int n,t; //车站数和约定的时间
int tim[55]; //每个车站的行走时间
int m1,m2;
int hav_train[300][55][2]; //某个时间点某个车站某个方向有木有车
int dp[255][55]; //某个时间某个车站的已经等待时间
void add_train(int tt, int f) { //某个时间某个方向发车
if(!f) {
hav_train[tt][1][0] = 1; //f为0车站从右边出发
for(int i = 1; i < n-1; i++) {
tt = tt+tim[i];
if(tt > 200) break; //已经超过约定的最大时间
hav_train[tt][i+1][0] = 1; //f为0车站从右边出发
}
}
else {
hav_train[tt][n][1] = 1;
for(int i = n-1; i > 1; i--) {
tt = tt+tim[i];
if(tt > 200) break; //已经超过约定的最大时间
hav_train[tt][i][1] = 1; //f为0车站从右边出发
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
int rnd = 0;
while(scanf("%d",&n) == 1 && n) {
memset(hav_train,0,sizeof(hav_train));
scanf("%d",&t);
for(int i = 1; i <= n-1; i++) //只有n-1个间隔
scanf("%d",&tim[i]); //1代表1-2的时间
int tmp;
scanf("%d",&m1);
for(int i = 0; i < m1; i++) {
scanf("%d",&tmp);
add_train(tmp,0);
}
scanf("%d",&m2);
for(int i = 0; i < m2; i++) {
scanf("%d",&tmp);
add_train(tmp,1);
}
memset(dp,inf,sizeof(dp));
dp[0][1] = 0; //0时刻第一个车站等待时间为0
for(int i = 0; i <= t; i++) { //遍历每个时间和车站
for(int j = 1; j <= n; j++) {
dp[i+1][j] = min(dp[i+1][j],dp[i][j]+1);
if(hav_train[i][j][0]) dp[i+tim[j]][j+1] = min(dp[i+tim[j]][j+1],dp[i][j]);
if(hav_train[i][j][1]) dp[i+tim[j-1]][j-1] = min(dp[i+tim[j-1]][j-1],dp[i][j]);
}
}
if(dp[t][n] < inf) printf("Case Number %d: %d\n",++rnd,dp[t][n]);
else printf("Case Number %d: impossible\n",++rnd);
}
return 0;
}