这是一道DP题。
感觉稍微有一点感悟,dp就像是一棵树的底层树叶,我们要做的就是往上开始堆。
这道题有两个变量,一个是时间,一个是位置。边界就是t = T,s(站台) = n时,d[t][s] = 0;表示的是你需要在站台等待的时间,仅指你不在地铁上的时间。所以有三种状态:一种是你上一秒在站台上等,现在再等一秒钟;第二种是左边有车过来,所以等待的时间就是到下一个站台的等待时间(车上的时间不算)。我们从d[T][n]开始往前堆,就会得到最优解。
#include <iostream>
#include <bits/stdc++.h>
#define maxn 1000
#define INF 0x3f3f3f3f
using namespace std;
int t[maxn];
int hasTrain[maxn][maxn][2];//t s
int d[maxn][maxn];
int main() {
int n,T;
int M1,M2;
int d1,d2;
int kase = 0;
while (cin>>n && n){
cin>>T;
memset(hasTrain,0, sizeof(hasTrain));
memset(t,0,sizeof(t));
memset(d,INF, sizeof(d));
for(int i = 1;i<=n-1;i++){
cin>>t[i];
}
//M1
cin>>M1;
int sum = 0;
for(int i = 1;i<=M1;i++)
{
cin>>d1;
//deal
hasTrain[d1][1][0] = 1;
sum = d1;
for(int j = 1;j<=n-1;j++){
sum+=t[j];
hasTrain[sum][j+1][0] = 1;
}
}
//M2
cin>>M2;
for(int i = 1;i<=M2;i++)
{
cin>>d2;
//deal
hasTrain[d2][n][1] = 1;
sum = d2;
for(int j = n-1;j>=1;j--){
sum+=t[j];
hasTrain[sum][j][1] = 1;
}
}
//deal
d[T][n] = 0;
for(int i = T-1;i>=0;i--){
for(int j = n;j>=1;j--){
d[i][j] = d[i+1][j] + 1;
//--->
if(j<n && i+t[j]<=T && hasTrain[i][j][0] ){
d[i][j] = min(d[i][j],d[i+t[j]][j+1]);
}
//<---
if(j>1 && i + t[j-1]<=T && hasTrain[i][j][1]){
d[i][j] = min(d[i][j],d[i+t[j-1]][j-1]);
}
}
}
cout<<"Case Number "<<++kase<<": ";
if(d[0][1]>=INF) cout<<"impossible\n";
else cout<<d[0][1]<<"\n";
}
return 0;
}
/**
4
55
5 10 15
4
0 5 10 20
4
0 5 10 15
4
18
1 2 3
5
0 3 6 10 12
6
0 3 5 7 12 15
2
30
20
1
20
7
1 3 5 7 11 13 17
0
**/