您的位置:首页 > 其它

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)卡住我的问题是怎么找到下面那个平台呢?后来想了想,暴力啊。。。(真是傻了==

我们只需要对所有的台阶按高度进行从低到高的排序就好了,然后我们从低到高的依次进行更新就可以了。

#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加油!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: