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

一、题目

某城市的地铁是线性的,有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。

原文地址:https://www.cnblogs.com/lfri/p/9439791.html

时间: 2024-07-28 23:36:36

动态规划初步--城市里的间谍的相关文章

uva1025城市里的间谍

某城市地铁是线性的,有n(2≤n≤50)个车站,从左到右编号1~n.有M1辆列车从第1站开始往右开,还有M2辆列车从第n站开始往左开. 列车在相邻站台间所需的运行时间是固定的,因为所有列车的运行速度是相同的. 在时刻0,Mario从第1站出发,目的在时刻T(0≤T≤200)会见车站n的一个间谍.在车站等车时容易被抓,所以她决定尽量躲在开动的火车上,让在车站等待的时间尽量短. 列车靠站停车时间忽略不计,且Mario身手敏捷,即时两辆方向不同的列车在同一时间靠站,Mario也能完成换乘. [输入格式

UVa 1025 城市里的间谍

https://vjudge.net/problem/UVA-1025 题意:一个间谍要从第一个车站到第n个车站去会见另一个,在是期间有n个车站,有来回的车站,让你在时间T内时到达n,并且等车时间最短,输出最短等车时间. 思路:先用一个has_train[t][i][0]来表示在t时刻,在车站i,是否有往右开的车.同理,has_train[t][i][1]用来保存是否有往左开的车. 用d(i,j)表示时刻i,你在车站j,最少还需要等待多长时间.边界条件是d(T,n)=0,其他d(T,i)为正无穷

UVA1025 城市里的间谍 A Spy in the Metro

#include<iostream> #include<cstdio> #include<memory.h> using namespace std; #define min(a,b) (a)<(b)?(a):(b) #define INF 0x3f3f3f3f #define N 55 #define M 220 int k,n,T,M1,M2,a,b; int t[N]; int f[M][N]; bool trn[M][N][2]; int main(){

UVA城市里的间谍

Solution 这一道题的状态很好想,用f[i][j]来表示第i秒在第j个车站至少要等多久,预处理出在第i秒第j个车站是否有车,注意数据可能会超过T,要注意清零. Code #include<bits/stdc++.h> using namespace std; const int N=55; int t[N],ht[10005][N][2],cnt,k,n,T,m1,f[10005][N]; int main(){ freopen("a.in","r"

动态规划初步(一)

动态规划初步 前言: 定个小目标,10天之内学会动态规划的简单问题,解决一小部分动态规划. 正文: 对于动态规划完全是小白的,可以看看http://www.cnblogs.com/sdjl/articles/1274312.html. 以LRJ紫书为参考. 第一题: http://acm.nyist.net/JudgeOnline/problem.php?pid=16 描述有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者

动态规划初步

经典问题一:最大连续子段和问题 原文借鉴 风仲达 :http://blog.csdn.net/liufeng_king/article/details/8632430 (给自己看的,抄一下也没问题吧~~~) 问题: 给出一段数字,假设有n个,有正有负,要你求最大的连续字段和.如:( -2,11,-4,13,-5,-2 )最大子段是{ 11,-4,13 }其和为20. 白痴的枚举法(n^3)的解法就不说了. 下面主要介绍两种方法: (1)分治法求解 分治法思路如下: 将序列a[1:n]分成长度相等

紫书第9章 动态规划初步

9.1 数字三角形 9.1.2 记忆化搜索与递推 方法1:递归计算.程序如下(需注意边界处理): int solve(int i,int j) { return a[i][j] + (i==n ?0:max(solve(i+1,j),solve(i+1,j+1)); } 用直接递归的方法计算状态转移方程,效率往往十分低下.其原因是相同的子问题被重复计算了多次. 方法2:递推计算.程序如下(需再次注意边界处理): int i, j; for(j = 1; j <= n; j++) d[n][j]

算法之动态规划初步(Java版)

概述: 算法的重要性是不言而喻的. 可能是你会不屑于听这样的话,是因为在我们的实际开发中,用到算法的地方真是太少了.对于这一点我并不否认,因为对于一个初级的开发者而言,算法显得太过高深了.如果我们想去实现一个功能,通常的做法就是百度或是Google.这就是为什么会有那么一句调侃之辞:我们不生产代码,我们只是代码的搬运工. 当我们已经完成了初级开发者的这一过程时,我们应该想着怎么去优化自己的代码,从而让自己的代码更加优美,也更显B格. 动规的使用场景: 动态规划是对回溯算法的一种改进. 我们知道回

第9章 动态规划初步

说一说这一章写博客的感受吧!感觉就是写的字太多了,表达的不太清晰,不如其他博主几句话就说明了问题,所以这是要改正的,有的地方回去再看都不一定看的懂, 所以需要改进啊!然后就是总结第9章的事情了,感觉不能再向之前一样完全对照书来总结(这样看书不是更好吗?),所以必须有自己的想法,这样的博客才更有意义. 动态规划,不同于其他的算法,是一种分析问题的思想,需要深入问题去挖掘(最优子结构.重叠子问题.最优解等等),可能对初学者来说是一道坎,但是不要着急,认真 分析,多看多想就是了(貌似是废话).从经典的