动态规划初步--城市里的间谍

一、题目

某城市的地铁是线性的,有n(2 ≤ n ≤ 50)个车站,从左到右编号为1~n。有M1辆车从第一站开始往右开,还有M2辆从第n站开始往左开。在时刻0,Mario从第一站出发,目的是在T时刻会见在n站的一个间谍。要求其在车站的等待时间足够短。

二、解题思路

状态由当前时间和当前所在站决定,我们可以用dp[i][j]表示在时刻t,第i站最少还需要等待的时间。易只T时刻的情况容易确定,

dp[T][j] = (j == n ? INF : 0),而T时刻之前的dp值,可以由T时刻及其之后的决定。

即dp[i][j] = max(dp[i][j] + 1,dp[i + t[j]][j + 1],dp[i + t[j - 1][j - 1]]) (加入三种选择都存在时)

根据状态转移方程和边界值,我们就可以从下至上填满整个表格,dp[0][1]就是要求的。

三、代码实现

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<string.h>
 4 #include<stdbool.h>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 const int INF = 0x3f3f3f3f;
 9 const int maxn = 50 + 10;
10 const int maxt = 200 + 10;
11 int n, T, cost_time[maxn],M1,M2;
12 int dp[maxt][maxn];  //dp[t][i]表示在时刻t,第i站最少还需要等待的时间
13 int has_train[maxt][maxn][2];  //has_train[i][j][0]表示i时刻,在j车站有开往左的火车,has_train[i][j][1]表示i时刻,在j车站有开往右的火车
14 int kase = 1;
15 
16 void slove()
17 {
18     memset(dp, 0, sizeof(dp));
19     
20     for (int i = 1; i <= n - 1; i++)  dp[T][i] = INF;    //时刻T,在非n的站,是不可能的,把等待时间设置为无穷大
21     dp[T][n] = 0;        //时刻T,在第n站,等待时间为0 
22 
23     for (int  i = T- 1; i >=  0; i--)
24     {
25         for (int j = 1; j <= n; j++)
26         {
27             dp[i][j] = dp[i + 1][j] + 1;
28             if (j < n && has_train[i][j][1] && i + cost_time[j] <= T)
29                 dp[i][j] = min(dp[i][j], dp[i + cost_time[j]][j + 1]);
30             if (j > 1 && has_train[i][j][0] && i + cost_time[j - 1] <= T)
31                 dp[i][j] = min(dp[i][j], dp[i + cost_time[j - 1]][j - 1]);
32         }
33     }
34     printf("Case Number %d: ", kase++);
35     if (dp[0][1] >= INF)  printf("impossible\n");
36     else  printf("%d\n", dp[0][1]);
37 }
38 
39 int main()
40 {
41     while (scanf("%d",&n) == 1 && n)
42     {
43         memset(has_train, 0, sizeof(has_train));        //这里必须清零
44         scanf("%d", &T);
45         for (int i = 1; i < n; i++)
46             scanf("%d", &cost_time[i]);
47 
48         scanf("%d", &M1);
49         int start;
50         for (int i = 0; i < M1; i++)
51         {
52             scanf("%d", &start);
53             int tmp = 0;
54             for (int j = 1; j <= n && start + tmp <= T; j++)    //只需考虑T之内的
55             {
56                 has_train[start + tmp][j][1] = true;
57                 if(j != n)  tmp += cost_time[j];        //cost_time不能取到n
58             }
59         }
60 
61         scanf("%d", &M2);
62         for (int i = 0; i < M2; i++)
63         {
64             scanf("%d", &start);
65             int tmp = 0;
66             for (int j = n; j >= 1 && start + tmp <= T; j--)
67             {
68                 has_train[start + tmp][j][0] = true;
69                 tmp += cost_time[j - 1];
70             }
71         }
72         
73         slove();
74     }
75     return 0;
76 }

四、经验

ctime变量与标准库里自带的冲突了;之前数组开小了,导致Runtime error。

猜你喜欢

转载自www.cnblogs.com/lfri/p/9439791.html
今日推荐