zoukankan      html  css  js  c++  java
  • poj_1661Help Jimmy

    Help Jimmy
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 7549   Accepted: 2405

    Description

    "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
    Jimmy 跳到一块板上后,可以有两种选择,向左走,或向右走。走到左端和走到右端所需的时间,是很容易算的。如果我们能知道,以左端为起点到达地面的最短时间,和以右端为起点到达地面的最短时间,那么向左走还是向右走,就很容选择了。因此,整个问题就被分解成两个子问题,即Jimmy 所在位置下方第一块板左端为起点到地面的最短时间,和右端为起点到地面的最短时间。这两个子问题在形式上和原问题是完全一致的。将板子从上到下从1 开始进行无重复的编号(越高的板子编号越小,高度相同的几块板子,哪块编号在前无所谓),那么,和上面两个子问题相关的变量就只有板子的编号,所以,本题目的“状态”就是板子编号,而一个“状态”对应的“值”有两部分,是两个子问题的解,即从该板子左端出发到达地面的最短时间,和从该板子右端出发到达地面的最短时间。不妨认为Jimmy 开始的位置是一个编号为0,长度为0 的板子,假设LeftMinTime(k)表示从k 号板子左端到地面的最短时间,RightMinTime(k)表示从k 号板子右端到地面的最短时间,那么,求板子k 左端点到地面的最短时间的方法如下:
    if ( 板子k 左端正下方没有别的板子) {
        if( 板子k 的高度 h(k) 大于Max)
            LeftMinTime(k) = ∞;
        else
            LeftMinTime(k) = h(k);
    }
    else if( 板子k 左端正下方的板子编号是m )
        LeftMinTime(k) = h(k)-h(m) + Min( LeftMinTime(m) + Lx(k)-Lx(m), RightMinTime(m) + Rx(m)-Lx(k));
    }
        上面,h(i)就代表i 号板子的高度,Lx(i)就代表i 号板子左端点的横坐标,Rx(i)就代表i号板子右端点的横坐标。那么 h(k)-h(m) 当然就是从k 号板子跳到m 号板子所需要的时间,Lx(k)-Lx(m) 就是从m 号板子的落脚点走到m 号板子左端点的时间,Rx(m)-Lx(k)就是从m号板子的落脚点走到右端点所需的时间。
        求RightMinTime(k)的过程类似。
        不妨认为Jimmy 开始的位置是一个编号为0,长度为0 的板子,那么整个问题就是要求LeftMinTime(0)。
        输入数据中,板子并没有按高度排序,所以程序中一定要首先将板子排序。


    point坐标写错N个,WA N次。没有注意从起点直接下落,wa。。。

    为爱debug,期末要挂科。。。

    代码:



    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAX = 999999;
    struct Point{
    	int x;
    	int y;
    	int height;
    }point[1005];
    
    bool cmp(Point a, Point b)
    {
    	return a.height < b.height;
    }
    int dp[1005][1005];
    int n, num;
    
    void MinTime()
    {
    	int next_x, next_y;
    	bool flag_x, flag_y;
    	dp[1][point[1].x] = point[1].height;
    	dp[1][point[1].y] = point[1].height;
    	for(int i = 2; i <= n + 1; i++)
    	{
    		flag_x = false;
    		for(int j = i - 1; j >= 1; j--)
    		{
    			if(point[j].x <= point[i].x && point[i].x <= point[j].y)
    			{
    				next_x = j;
    				flag_x = true;
    				break;
    			}
    		}
    		if(flag_x)
    		{
    			if(point[i].height - point[next_x].height <= num)  //注意中途也要考虑小于最大下降高度,摔死老鼠怎么办?
    				dp[i][point[i].x] = point[i].height - point[next_x].height + min(dp[next_x][point[next_x].x]+point[i].x-point[next_x].x,dp[next_x][point[next_x].y]+point[next_x].y-point[i].x);
    			else dp[i][point[i].x] = MAX;
    		}
    		else
    		{
    			if(point[i].height > num)
    				dp[i][point[i].x] = MAX;
    			else
    				dp[i][point[i].x] = point[i].height;
    		}
    
    
    		flag_y = false;
    		for(int j = i - 1; j >= 1; j--)
    		{
    			if(point[j].y >= point[i].y && point[i].y >= point[j].x)
    			{
    				next_y = j;
    				flag_y = true;
    				break;
    			}
    		}
    		if(flag_y)
    		{
    			if(point[i].height - point[next_y].height <= num)
    				dp[i][point[i].y] = point[i].height - point[next_y].height + min(dp[next_y][point[next_y].x]+point[i].y-point[next_y].x,dp[next_y][point[next_y].y]+point[next_y].y-point[i].y);
    			else dp[i][point[i].y] = MAX;
    		}
    		else
    		{
    			if(point[i].height > num)
    			{
    				dp[i][point[i].y] = MAX;
    			}
    			else
    			{
    				dp[i][point[i].y] = point[i].height;
    			}
    		}
    	}
    }
    
    int main()
    {
    	freopen("in.txt","r",stdin);
    	int t, x, y, i;
    	cin >> t;
    	while(t--)
    	{
    		memset(dp, 0, sizeof(dp));
    		memset(point, 0, sizeof(point));
    		cin >> n >> x >> y >> num;
    		for(i = 1; i <= n; i++)
    		{
    			cin >> point[i].x >> point[i].y >> point[i].height;
    		}
    		point[n+1].x = point[n+1].y = x;
    		point[n+1].height = y;
    		sort(point + 1, point + n + 2, cmp);
    		MinTime();
    		cout<<dp[n+1][point[n+1].x]<<endl;
    	}
    	return 0;
    }



  • 相关阅读:
    struts2_20140720
    使用jsp生成验证码
    JAVA笔记1-00
    Myeclipse 2014配置SVN详细图解
    排查IDEA 全局搜索快捷键Ctrl +Shift+F不起作用的原因和解决方法
    linux,java.net.UnknownHostException:XXX:XXX: Name or service not known
    mac使用技巧
    谈创业
    小白3步完成替换tomcat域名
    linux下yum安装redis以及使用
  • 原文地址:https://www.cnblogs.com/lgh1992314/p/5835269.html
Copyright © 2011-2022 走看看