zoukankan      html  css  js  c++  java
  • Help Jimmy 【POJ

    题目链接: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;
    	}
    	
    }```
    
    
  • 相关阅读:
    Junit。。。
    TCP
    InetAddress
    URL
    【转】Hello SDL
    批量移动文件
    在阿里云Ubuntu 14.04.5 LTS下安装nethogs0.8.5
    十二银元分三次找一假
    SQL解析
    POI
  • 原文地址:https://www.cnblogs.com/neflibata/p/12871753.html
Copyright © 2011-2022 走看看