POJ1661(KB12-M DP)

Help Jimmy

Description

"Help Jimmy" 是在下图所示的场景上完成的游戏。 

场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

设计一个程序,计算Jimmy到底地面时可能的最早时间。

Input

第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是四个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面),X和Y是Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所有坐标的单位都是米。

Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。

Output

对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。

Sample Input

1
3 8 17 20
0 10 8
0 10 13
4 14 3

Sample Output

23

Source

POJ Monthly--2004.05.15 CEOI 2000

 1 //2017-04-06
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6
 7 using namespace std;
 8
 9 const int inf = 0x3f3f3f3f;
10 struct node{
11     int l, r, h;
12     bool operator<(const node x)
13     {
14         return this->h > x.h;
15     }
16 }platform[1005];
17 int dpl[1005], dpr[1005];//dpl[i]记录从第i块平台左端点落地所需的最短时间,dpr[i]记录从第i块平台右端点落地所需的最短时间
18 int n, MAX;
19
20 int dfs(int x, int y, int ptr)//输入参数表示从第ptr块平台,位于(x, y)点开始搜索
21 {
22     if(dpl[ptr] != inf && dpr[ptr] != inf)
23       if(y-platform[ptr].h <= MAX)
24         if(platform[ptr].l <= x && platform[ptr].r >= x)
25           return y-platform[ptr].h+min(dpl[ptr]+x-platform[ptr].l, dpr[ptr]+platform[ptr].r-x);//记忆化搜索,返回位于(x, y)点向左右走的最短时间
26     int l, r, h;
27     for(int i = ptr; i < n; i++){
28         l = platform[i].l;
29         r = platform[i].r;
30         h = platform[i].h;
31         if(h <= y && y-h <= MAX){
32             if(x >= l && x <= r){
33                 if(h == 0)return y-h;
34                 else{
35                     int left = dfs(l, h, i+1);//向左走
36                     dpl[i] = min(dpl[i], left);
37                     int right = dfs(r, h, i+1);//向右走
38                     dpr[i] = min(dpr[i], right);
39                     return y-h+min(dpl[i]+x-l, dpr[i]+r-x);
40                 }
41             }
42         }
43     }
44     return inf;
45 }
46
47 int main()
48 {
49     int T, x, y, ans;
50     scanf("%d", &T);
51     while(T--)
52     {
53         scanf("%d%d%d%d", &n, &x, &y, &MAX);
54         for(int i = 0; i < n; i++){
55             scanf("%d%d%d", &platform[i].l, &platform[i].r, &platform[i].h);
56             dpl[i] = dpr[i] = inf;
57         }
58         //加入地面这一块平台,高度为0,左右边界无穷
59         platform[n].h = 0;
60         platform[n].l = -inf;
61         platform[n].r = inf;
62         dpl[n] = dpr[n] = inf;
63         n++;
64         sort(platform, platform+n);
65         int l, r, h, i;
66         for(i = 0; i < n; i++)//找到下落遇到的地一块平台,从这块平台开始搜索
67         {
68             l = platform[i].l;
69             r = platform[i].r;
70             h = platform[i].h;
71             if(h <= y && y-h <= MAX)
72               if(x >= l && x <= r)
73                 break;
74         }
75         ans = dfs(x, h, i)+y-h;
76         printf("%d\n", ans);
77     }
78
79     return 0;
80 }
时间: 2024-12-08 02:55:38

POJ1661(KB12-M DP)的相关文章

POJ--1661(DP)

jimmy的一个游戏,可以从左右端点往下跳,每秒走一米或落一米,落的超过_max会摔死,问到达地面的最短时间,测试用例保证一定有解. 一道基础的DP,太tm考验我了,有些细节容易处理不好,中间卡了下,写错好几个地方,不过我居然一遍过了也真是水-- 用了二维的状态,dp[k][0],dp[k][1]分别表示从上一个端点落下来并移动到本k层的左.右端点需要的时间,如果到不了直接在上一个状态恢复到INF表示从此端点掉落会摔死,预处理把开始点也加进去好处理一些,把地面单独判断了下. 代码: #inclu

POJ1661 Help Jimmy(dp)

"Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒.当Jimmy落到某个平台上时,游戏 者选择让它向左还是向右跑,它跑动的速度也是1米/秒.当Jimmy跑到平台的边缘时,开始继续下落.Jimmy每次下落的高度不能超过MAX米,不然就 会摔死,游戏也会结束. 设计一个程序,计算Jimmy到底地面时可能的最早时间. Inpu

poj-1661 Help Jimmy 【DP】

Help Jimmy Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8955   Accepted: 2871 Description "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒.当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑

poj1661 (DP)

题目链接:http://poj.org/problem?id=1661 思路: 把初始位置看成左,右端点均为x0,即长度为0,高度为y0的一个平台,按照平台高度从低到高排序.用dp[i][0],dp[i][1]分别表示从第i个平台的左端,右端到地面的最短时间.tmp=get_next(i,0)表示第i个平台左端点下的平台的编号(若为-1表示下方已无平台),同理tmp=get_next(i,1)表示第i个平台右端点下的平台编号.因为求最小值,所以要将dp初始化为inf,因此状态转移方程如下(注意若

「kuangbin带你飞」专题十二 基础DP

layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 传送门 A.HDU1024 Max Sum Plus Plus 题意 给你N个数,然后你分成M个不重叠部分,并且这M个不重叠部分的和最大. 思路 动态规划最大m字段和,dp数组,dp[i][j]表示以a[j]结尾的,i个字段的最大和 两种情况:1.第a[j

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.