poj(1661)——Help Jimmy(二维dp)
2015-08-23 22:22
453 查看
题意:
现在共有N个平台,然后一开始它站在坐标为(x,y)的位置,然后它每次下落与往左右走的速度都是1m/s,并且它每次下落的距离不能超过max米。
告诉你每个平台的左右端点的坐标与它的高度,然后问你它到达地面的最早时间是多少。
注:如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。
思路:
这道题一开始卡了我好久。。(我一开始还以为这道题又和Mandown那道题相似,那道题是用线段树过的。不过我觉得那道题好像也可以用这道题相类似的方法过)
不过这道题状态方程的定义也让我更好的增长了思路,
1)首先定义状态:dp[i][0]:表示从i平台的左边走到地面的最短时间
dp[i][1]:表示从i平台的右边走到地面的最短时间
这样定义子问题就可以往后面推了。
2)状态转移:dp[i][0]=h[i]-h[m]+min(dp[m][0]+l[i]-l[m],dp[m][1]+r[m]-l[i]); dp[i][1]=h[i]-h[m]+min(dp[m][1]+r[m]-r[i],dp[m][0]+r[i]-l[m]);
//这里m代表的意义是i平台下面的那个平台
3)卡住我的问题是怎么找到下面那个平台呢?后来想了想,暴力啊。。。(真是傻了==
我们只需要对所有的台阶按高度进行从低到高的排序就好了,然后我们从低到高的依次进行更新就可以了。
不断的进步!!加油,hades,DP加油!
现在共有N个平台,然后一开始它站在坐标为(x,y)的位置,然后它每次下落与往左右走的速度都是1m/s,并且它每次下落的距离不能超过max米。
告诉你每个平台的左右端点的坐标与它的高度,然后问你它到达地面的最早时间是多少。
注:如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。
思路:
这道题一开始卡了我好久。。(我一开始还以为这道题又和Mandown那道题相似,那道题是用线段树过的。不过我觉得那道题好像也可以用这道题相类似的方法过)
不过这道题状态方程的定义也让我更好的增长了思路,
1)首先定义状态:dp[i][0]:表示从i平台的左边走到地面的最短时间
dp[i][1]:表示从i平台的右边走到地面的最短时间
这样定义子问题就可以往后面推了。
2)状态转移:dp[i][0]=h[i]-h[m]+min(dp[m][0]+l[i]-l[m],dp[m][1]+r[m]-l[i]); dp[i][1]=h[i]-h[m]+min(dp[m][1]+r[m]-r[i],dp[m][0]+r[i]-l[m]);
//这里m代表的意义是i平台下面的那个平台
3)卡住我的问题是怎么找到下面那个平台呢?后来想了想,暴力啊。。。(真是傻了==
我们只需要对所有的台阶按高度进行从低到高的排序就好了,然后我们从低到高的依次进行更新就可以了。
#include<stdio.h> #include<string.h> #include<math.h> #include<map> #include<set> #include<queue> #include<iostream> #include<algorithm> using namespace std; #define maxn 1111 #define inf 99999999 int dp[maxn][2]; int n,x,y,lmax; struct node{ int l,r; int h; }a[maxn]; bool cmp(node a,node b){ return a.h<b.h; } void leftime(int x){ int k=x-1; while(k>=0&&a[x].h-a[k].h<=lmax){ if(k==0){ dp[x][0]=a[x].h; } if(k>0&&a[x].l>=a[k].l&&a[x].l<=a[k].r){ dp[x][0]=a[x].h-a[k].h+min(dp[k][0]+a[x].l-a[k].l,dp[k][1]+a[k].r-a[x].l); return ; } else k--; } if(a[x].h-a[k].h>lmax) dp[x][0]=inf; } void rightime(int x){ int k=x-1; while(k>=0&&a[x].h-a[k].h<=lmax){ if(k==0){ dp[x][1]=a[x].h; } if(k>0&&a[x].r>=a[k].l&&a[x].r<=a[k].r){ dp[x][1]=a[x].h-a[k].h+min(dp[k][1]+a[k].r-a[x].r,dp[k][0]+a[x].r-a[k].l); return ; } else k--; } if(a[x].h-a[k].h>lmax) dp[x][1]=inf; } int getans(){ for(int i=1;i<=n+1;i++){ rightime(i); leftime(i); } return min(dp[n+1][0],dp[n+1][1]); } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d%d%d",&n,&x,&y,&lmax); for(int i=1;i<=n;i++){ scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].h); } a[0].l=x; a[0].r=x; a[0].h=y; a[n+1].l=-20000; a[n+1].r=20000; a[n+1].h=0; sort(a,a+n+2,cmp); int ans=getans(); printf("%d\n",ans); } }
不断的进步!!加油,hades,DP加油!
相关文章推荐
- C语言运算符优先级表
- 高阶MapReduce_1_链接多个MapReduce作业
- URAL1277Cops and Thieves Dinic最大流
- Intellij IDEA工具Java web 环境搭建
- RedHat7.0下MySQL5.6.24数据库的安装以及数据库存储目录迁移
- css盒子模型
- leetcode 169: Majority Element
- 用Lucene索引数据库
- Android快速开发框架-AndroidFine,GitHub开源
- 黑马程序员——集合——Set集合,增强for循环,数据结构,泛型,Collections集合工具类
- 总结篇(2)-----第一遍机房收费系统(上机)
- Tomcat与Web应用的配置
- 各种小空间总结
- matlab简单实现SVD的推荐
- python笔记 5
- JavaSE复习日记 : 实例化对象/构造方法和this关键字
- 大数据发展方向
- Linux命令:ls命令使用方法
- 翻转子串
- ubuntu 安装wxpython以及boa-constructor