总时间限制: 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;
}