Help Jimmy 【POJ - 1661】DP

题目链接:https://vjudge.net/problem/POJ-1661
“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

首先肯定是要按高度排序的
然后就是找状态转移方程了,f[i][0]表示落到第i块板子左边的最短时间,f[i][1]是到第i块板子右边的最短时间。
从第j块板子左端可以落到板子i上时
f[i][0]=min(f[i][0],f[j][0]+t1)
f[i][1]=min(f[i][0],f[j][0]+t2) (t1,t2分别表示第j块左端到第i块左右的时间)
第j块右端可以落到板子i上时与上面类似。
下面就只剩下怎么判断板子j是否可以落到板子i了(不在写左右了,但是还是要区分的):
1.板子j高度要大于板子i,且高度差不能大于max
2.落点要在板子i的范围内
3.也是最重要的一点,板子j到板子i的中间不能有其他板子,仔细看上面的图,从一块板子落下有且最多落到一块板子,所以可以标记一下板子j可以落到那个板子,如果板子j没有被标记,且满足前两个条件那它就可以落到i,状态转移即可,之后还要把j标记一下。
直接暴击就行,复杂度O(n^2)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1010;
int n,m,t,x,y,st[N][2];//st[i][0]标记第i块板子左端可以落到那个板子,st[i][1]就是右端
struct node
{
	int l,r,h;
}e[N];
ll f[N][2];
bool cmp(node a,node b)
{
	if(a.h==b.h) return a.l<b.l;//这里其实无所谓加不加
	return a.h>b.h;
}
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>x>>y>>m;
		for(int i=1;i<=n;i++)
		{
			int a,b,c;
			cin>>a>>b>>c;
			e[i]={a,b,c};
		}
		e[0]={x,x,y};
		sort(e+1,e+n+1,cmp);
		memset(st,-1,sizeof st);
		memset(f,0x3f,sizeof f);
		f[0][0]=f[0][1]=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<i;j++)
			{
				if(e[j].h-e[i].h>0&&e[j].h-e[i].h<=m)//条件1
				{
					if(e[j].l>=e[i].l&&e[j].l<=e[i].r)//条件2
					{
						if(st[j][0]==-1)//条件3
						{
							f[i][0]=min(f[i][0],f[j][0]+e[j].h-e[i].h+e[j].l-e[i].l);
							f[i][1]=min(f[i][1],f[j][0]+e[j].h-e[i].h+e[i].r-e[j].l);
							st[j][0]=i;
						}
					}
					if(e[j].r>=e[i].l&&e[j].r<=e[i].r)//条件2
					{
						if(st[j][1]==-1)//条件3
						{
							f[i][0]=min(f[i][0],f[j][1]+e[j].h-e[i].h+e[j].r-e[i].l);
							f[i][1]=min(f[i][1],f[j][1]+e[j].h-e[i].h+e[i].r-e[j].r);
							st[j][1]=i;
						}
					}
				}
			}
		}
		ll ans=0x3f3f3f3f3f3f3f3f;
		for(int i=0;i<=n;i++)
			if(e[i].h<=m)
			{
				if(st[i][0]==-1) ans=min(ans,f[i][0]+e[i].h);
				if(st[i][1]==-1) ans=min(ans,f[i][1]+e[i].h);
			}
		cout<<ans<<endl;
	}
	
}```

posted @ 2020-04-15 15:22  Neflidata  阅读(3)  评论(0编辑  收藏  举报