1.题目描述:点击打开链接
2.解题思路:本题利用动态规划解决,时刻i和所在的车站j构成了一个状态,每个状态都有三种决策:(1)等待1分钟。(2)搭乘向右开的车(如果有)。(3)搭乘向左开的车(如果有)。如果用d(i,j)表示在时刻i,位于车站j时最少的等待时间,那么对于三种决策,可得到如下的状态转移方程:
(1) d(i,j)=d(i+1,j)+1;
(2) d(i,j)=min(d(i,j),d(i+t[j],j+1));
(3) d(i,j)=min(d(i,j),d(i+t[j-1],j-1));
处理状态之前可以先用数组has_train表示时刻i,位于车站j,有无向右(向左)的车。
3.代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define INF 9999999
#define maxn 250+50
int T, n, m1, m2;
int t[maxn];
int a[maxn], b[maxn];
int has_train[maxn][maxn][2];
int dp[maxn][maxn];
int main()
{
//freopen("test.txt", "r", stdin);
int kase = 0;
while (scanf("%d", &n) == 1 && n)
{
memset(has_train, 0, sizeof(has_train));
scanf("%d", &T);
t[0] = 0;
t[n] = 0;
for (int i = 1; i <= n - 1; i++)
scanf("%d", t + i);
scanf("%d", &m1);
for (int i = 1; i <= m1; i++)
{
scanf("%d", a + i);
int sum = a[i];
for (int j = 0; j <= n - 1; j++)
{
sum += t[j];
has_train[sum][j + 1][0] = 1;
}
}
scanf("%d", &m2);
for (int i = 1; i <= m2; i++)
{
scanf("%d", b + i);
int sum = b[i];
for (int j = n; j >= 1; j--)
{
sum += t[j];
has_train[sum][j][1] = 1;
}
}
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&&has_train[i][j][0] && i + t[j] <= T)
dp[i][j] = min(dp[i][j], dp[i + t[j]][j + 1]);
if (j>1 && has_train[i][j][1] && i + t[j - 1] <= T)
dp[i][j] = min(dp[i][j], dp[i + t[j - 1]][j - 1]);
}
cout << "Case Number " << ++kase << ": ";
if (dp[0][1] >= INF)cout << "impossible\n";
else cout << dp[0][1] << '\n';
}
return 0;
}