动态规划,紫书上面已经解释很清楚了,逆向推理,从最后一个状态顺推前面全部状态,最终得到dp[0][0],再进行一轮判断即可,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
using namespace std;
int N, T;
int train[500][500][2];
int timeInter[500];
int M1, M2;
int toLeft[60],toRight[60];
int dp[500][500];
int main(){
int Case = 1;
while (cin >> N){
if (N == 0) break;
memset(train,0,sizeof(train));
cin >> T;
for (int i = 0; i < N-1; i++) cin >> timeInter[i];
cin >> M1;
for (int i = 0; i < M1; i++) cin >> toRight[i];
cin >> M2;
for (int i = 0; i < M2; i++) cin >> toLeft[i];
for (int i = 0; i < M1; i++){
int t = toRight[i];
train[t][0][1] = 1;//时刻 车站编号 1 右
for (int j = 0; j < N-1; j++){
t += timeInter[j];
train[t][j+1][1] = 1;
}
}
for (int i = 0; i < M2; i++){
int t = toLeft[i];
train[t][N - 1][0] = 1;//0 左
for (int j = N - 2; j >= 0; j--){
t += timeInter[j];
train[t][j][0] = 1;
}
}
memset(dp,0,sizeof(dp));
dp[T][N - 1] = 0;
for (int i = 0; i < N - 1; i++) dp[T][i] = 1 << 20;
for (int i = T - 1; i >= 0; i--){
for (int j = 0; j < N; j++){
dp[i][j] = dp[i+1][j] + 1;
if (j < N - 1 && train[i][j][1] && i + timeInter[j] <= T){//right
dp[i][j] = min(dp[i][j],dp[i+timeInter[j]][j+1]);
}
if (j > 0 && train[i][j][0] && i + timeInter[j-1] <= T){//left
dp[i][j] = min(dp[i][j], dp[i + timeInter[j - 1]][j-1]);
}
}
}
cout << "Case Number "<<Case++<<": ";
if (dp[0][0] >= (1 << 20)) cout << "impossible" << endl;
else cout << dp[0][0] << endl;
}
return 0;
}