1661帮助 Jimmy

11 篇文章 0 订阅
10 篇文章 0 订阅

总时间限制: 1000ms 内存限制: 65536kB

描述

“Help Jimmy” 是在下图所示的场景上完成的游戏。

场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

设计一个程序,计算Jimmy到底地面时可能的最早时间。

输入

第一行是测试数据的组数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恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。

输出

对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。

样例输入

1
3 8 17 20
0 10 8
0 10 13
4 14 3

样例输出

23

来源 POJ Monthly–2004.05.15 CEOI 2000

**解题思路:先输入数据,然后对数据根据高度排序
按照高度小的编号在前,高度大的编号在后
设地面的编号为0,从下往上进行递推逐步根据第i块板及以前的已有信息推导出第i+1块板的maxleft和maxright.
在第i+1块板的时候,我们需要从第i块板开始找一块板,使当前板的向左或者向右可以落板。落板后我们就可以知道,当前板向左或向右的最小值,然后以此类推。找板的过程,时间复杂度为O(n).如果找到落板后,假如height>MAX的话,那么可设,min(i+1)=无穷大。
完。。。。。。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
/*先输入数据,然后对数据根据高度排序
按照高度小的编号在前,高度大的编号在后
设地面的编号为0,从下往上进行递推逐步根据第i块板及以前的已有信息推导出第i+1块板
的maxleft和maxright
*/
int maxl=-20005;
int maxr=20005;
int N,X,Y,MAX; 
struct node 
{
	int l,r,h;
}board[1005];
int minsuml[1005];
int minsumr[1005];
bool cmp(struct node a1,struct node a2)
{
	return a1.h<a2.h;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(minsuml,0,sizeof(minsuml));
		memset(minsumr,0,sizeof(minsumr));
		cin>>N>>X>>Y>>MAX;
		for(int i=1;i<=N;i++)
		cin>>board[i].l>>board[i].r>>board[i].h;
		board[0]={maxl,maxr,0};//地面
		board[N+1]={X,X,Y};//Jimmy的信息 
		sort(board+1,board+1+N,cmp);//按照高度排序 
		for(int i=1;i<=N+1;i++)
		{
			int flag_l=1;
			int flag_r=1;
			int l_len;
			int r_len;
			int height;
			for(int j=i-1;j>=0;j--)
		{
			if(flag_l+flag_r==0)
			break; 
			if(flag_l==1&&board[i].l>=board[j].l&&board[i].l<=board[j].r)//从左边下落
			{
				height=board[i].h-board[j].h;//高度差 
				l_len=board[i].l-board[j].l;//向左走的距离 
				r_len=board[j].r-board[i].l; //向右走的距离
				 if(j==0)//特判 
				l_len=0,r_len=0;
				if(height>MAX)//下面没有板又如何?必然会有跳板地面 
				minsuml[i]=20000;
				else
				minsuml[i]=min(minsuml[j]+l_len,minsumr[j]+r_len)+height;
				
				flag_l=0;
			 } 
			if(flag_r==1&&board[i].r>=board[j].l&&board[i].r<=board[j].r)//从右边下落 
			{
				height=board[i].h-board[j].h;//高度差 
				l_len=board[i].r-board[j].l;//向左走的距离 
				r_len=board[j].r-board[i].r; //向右走的距离 
				if(j==0)//特判 
				l_len=0,r_len=0;
				if(height>MAX)//下面没有板又如何?必然会有跳板地面 
				minsumr[i]=20000;
				else
				minsumr[i]=min(minsuml[j]+l_len,minsumr[j]+r_len)+height;
				flag_r=0;
			}	 
		} 
		}
		cout<<min(minsuml[N+1],minsumr[N+1])<<endl; 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值