POJ 1661 Help Jimmy(二维DP)

题目链接:http://poj.org/problem?id=1661

题目大意:

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

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

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

解题思路:根据题意易得无论如何都要下落H的高度,所以可以不用计算下落高度所需时间,直接计算水平走的最短时间最后加上高度即可,按平台高度从高到低排序,建立二维数组,dp[i][0]表示第i个平台往左走到达地面的最短水平时间,dp[i][1]表示第i个平台往右走到达地面的最短水平时间,于是有状态转移方程:

dp[i][0]=min(dp[j][0]+a[i].x1-a[j].x1,dp[j][1]+a[j].x2-a[i].x1), j是i左边下面的落点平台编号。

dp[i][1]=min(dp[j][1]+a[j].x2-a[i].x2,dp[j][0]+a[i].x2-a[j].x1),j是i右边下面的落点平台编号。

所以直接自底向上递推,每次往左或往右找到第一个落点平台计算最少时间,最后推到i=0(起始点)就可以了。

要注意一下①初始化dp为inf,dp[0][1]和dp[0][0]也要初始化为inf。

     ②找到第一个可掉落的平台计算之后,就break,不然会把下面几个平台都算进去。

     ③判断当找不到落点平台时,可能有三种情况:

        1)所在平台高度小于等于MAX,但下面没有平台

        2)下面有平台,但两平台高度差大于MAX

        3)下面没有平台,且所在平台高度大于MAX

      特判情况1),此时dp[i][0](或dp[i][1])为0

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=1e3+5;
 5 const int inf=1<<30;
 6
 7 struct node{
 8     int x1,x2,h;
 9 }a[N];
10
11 int dp[N][2];//从第i层0往左,1往右
12
13 bool cmp(node a,node b){
14     return a.h>b.h;
15 }
16
17 int main(){
18     int T;
19     scanf("%d",&T);
20     while(T--){
21         int n,X,H,MAX;
22         scanf("%d%d%d%d",&n,&X,&H,&MAX);
23         for(int i=1;i<=n;i++){
24             scanf("%d%d%d",&a[i].x1,&a[i].x2,&a[i].h);
25             dp[i][0]=dp[i][1]=inf;
26         }
27         sort(a+1,a+1+n,cmp);
28
29         //将起始点也当成一个平台
30         a[0].h=H;
31         a[0].x1=a[0].x2=X;
32         dp[n][0]=dp[n][1]=0;
33         dp[0][0]=dp[0][1]=inf;
34         //自底向上推
35         for(int i=n-1;i>=0;i--){
36             //往左走
37             for(int j=i+1;j<=n;j++){
38                 if(a[i].h-a[j].h<=MAX){
39                     if(a[j].x1<=a[i].x1&&a[j].x2>=a[i].x1){
40                         dp[i][0]=min(dp[j][0]+a[i].x1-a[j].x1,dp[j][1]+a[j].x2-a[i].x1);
41                         break;
42                     }
43                 }
44             }
45             //下面没平台且里地面高度不超过MAX
46             if(a[i].h<=MAX&&dp[i][0]==inf)
47                 dp[i][0]=0;
48
49             //往右走
50             for(int j=i+1;j<=n;j++) {
51                 if(a[i].h-a[j].h<=MAX){
52                     if(a[j].x2>=a[i].x2&&a[j].x1<=a[i].x2){
53                         dp[i][1]=min(dp[j][1]+a[j].x2-a[i].x2,dp[j][0]+a[i].x2-a[j].x1);
54                         break;
55                     }
56                 }
57             }
58             if(a[i].h<=MAX&&dp[i][1]==inf)
59                 dp[i][1]=0;
60         }
61         printf("%d\n",min(dp[0][1],dp[0][1])+H);
62     }
63     return 0;
64 } 
时间: 2024-08-19 14:17:18

POJ 1661 Help Jimmy(二维DP)的相关文章

[2016-03-29][POJ][1661][]Help Jimmy]

时间:2016-03-29 21:36:50 星期二 题目编号:[2016-03-29][POJ][1661][]Help Jimmy] #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n,x,y,maxh; struct Plat{ int l,r,h; bool operator < (const Plat & a)const{ ret

POJ 1984 Navigation Nightmare 二维带权并查集

题目来源:POJ 1984 Navigation Nightmare 题意:给你一颗树 k次询问 求2点之间的曼哈顿距离 并且要在只有开始k条边的情况下 思路:按照方向 我是以左上角为根 左上角为原点 dx[i]为i点距离根的x坐标 dy[]是y坐标 这两个可以通过路径压缩求出 只不过是二维而已 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int m

HDU 4901 The Romantic Hero(二维dp)

题目大意:给你n个数字,然后分成两份,前边的一份里面的元素进行异或,后面的一份里面的元素进行与.分的时候按照给的先后数序取数,后面的里面的所有的元素的下标一定比前面的大.问你有多上种放元素的方法可以使得前面异或的值和后面与的值相等. dp[x][y] 表示走到第x步,得到y这个数字一共有多少种方法. 但是需要注意这里得分一下,不能直接用dp数组存种数,你需要分一下从上一层过来的次数,和这一层自己可以到达的次数.然后取和的时候前后两个集合的种数进行乘法,注意边乘边取余. 顺便给一组数据: 4 3

二维dp(O(N^3)实现) zoj3230

1 #include<iostream> 2 #include<string.h> 3 #include<stdio.h> 4 #define maxn 125 5 using namespace std; 6 7 int cost[maxn][maxn],w[maxn][maxn]; 8 int dp[maxn][maxn]; 9 int N,M; 10 int main(){ 11 while(cin>>N>>M){ 12 if (N==0

hoj_10014_二维DP

The Triangle Time Limit: 1000ms, Special Time Limit:2000ms, Memory Limit:32768KB Total submit users: 952, Accepted users: 860 Problem 10014 : No special judgement Problem description 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 shows a number tr

XTU1168:Alice and Bob(二维DP)

摘要:Dota(Defence of the Ancients,远古的守护), 是指基于魔兽争霸3:冰封王座(暴雪娱乐公司出品)的多人即时对战自定义地图,可支持10个人同时连线游戏.Dota以对立的两个小队展开对战,通常是5v5,游戏目的是守护自己的远古遗迹(近卫方的生命之树.天灾方的冰封王座),同时摧毁对方的远古遗迹.DotA是目前唯一被暴雪娱乐公司官方认可的魔兽争霸RPG.Dota在大学生中的风靡程度令人咂舌,而随着玩家对游戏的理解深入,本身存在于游戏中的许多数学模型被挖掘出来进行研究.游戏

HDU 5074 Hatsune Miku(简单二维dp)

题目大意:给你一些音符之间的联系,给你一个串,让你求出这个串的最大值.-1的时候可以任意替代,其他情况必须为序列上的数. 解题思路:简单二维dp,分情况处理就可以了啊. Hatsune Miku Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 637    Accepted Submission(s): 458 Problem De

(review)zoj4800 二维dp 状态转移很灵活

1 #include<iostream> 2 #include<stdio.h> 3 4 using namespace std; 5 6 double dp[10005][125]; 7 double p[125][125]; 8 int pk[10005]; 9 10 int N,M; 11 12 double fmax(double a,double b){ 13 if(a-b>0) return a;else return b; 14 } 15 int main(){

NOJ1060 接苹果 二维DP

题目描述 很少有人知道奶牛爱吃苹果.农夫约翰的农场上有两棵苹果树(编号为1和2), 每一棵树上都长满了苹果.奶牛贝茜无法摘下树上的苹果,所以她只能等待苹果 从树上落下.但是,由于苹果掉到地上会摔烂,贝茜必须在半空中接住苹果(没有人爱吃摔烂的苹果).贝茜吃东西很快,她接到苹果后仅用几秒钟就能吃完.每一分钟,两棵苹果树其中的一棵会掉落一个苹果.贝茜已经过了足够的训练, 只要站在树下就一定能接住这棵树上掉落的苹果.同时,贝茜能够在两棵树之间 快速移动(移动时间远少于1分钟),因此当苹果掉落时,她必定站