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; }