Description
"Help Jimmy" 是在下图所示的场景上完成的游戏。
场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。
Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。
设计一个程序,计算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恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。
Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。
Output
对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。
Sample Input
1
3 8 17 20
0 10 8
0 10 13
4 14 3
Sample Output
23
思路:
关键:运用递归的思想用动态规划的数组实现
方法:将输入的数据按高度由高到底排序,然后从最高一个向下递归,根据条件判断做出相应的动作,利用数组存储相应的时间
实现考虑:
1.不妨认为Jimmy开始的位置是一个编号为0,长度为0的板子,那么整个问题就是要求LeftMinTime(0)。
2. 输入数据中,板子并没有按高度排序,所以程序中一定要首先将板子排序。
3. LeftMinTime(k)和RightMinTime(k)可以用同一个过程来实现(用一个布尔变量来区分)此处程序用的Flag
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
const long int Inf = 1000000;
int ncases;//声明一个变量存储一共几组数据
int n;//平台的数目
int x;//开始下落点的横坐标
int y;//开始下落点的竖坐标
int nmax;//一次下落的做大高度
//定义一个结构体,存储各板子的状态:板子左右横坐标和y坐标
struct PlatForm
{
int lx;
int rx;
int h;
}p[1010];
//定义两个数组分别存储从左边和右边下落的最短时间
int leftmin[1010];
int rightmin[1010];
//快速排序过程中用到的比较函数
int Compare(const void *e1, const void *e2)
{
struct PlatForm *p1, *p2;
p1 = (struct PlatForm *)e1;
p2 = (struct PlatForm *)e2;
return p2 -> h - p1 -> h;
}
//确定最短时间到达地面
int mintime(int L, int Flag)//L表示哪一块木板,flag表示哪一端,0表示左端,1表示右端
{
int y = p[L].h;
int i;
int x;
int ltime;
int rtime;
if(Flag)
{
x = p[L].lx;
}else
{
x = p[L].rx;
}
//从起点下面的一块木板开始遍历
for(i = L + 1; i <= n; ++i)
{
//i木板在起点下面则退出遍历
if(p[i].lx <= x && p[i].rx >= x)
break;
}
//对于起点下面有木板的情况
if(i <= n)
{
if(y - p[i].h > nmax)
return Inf;
}else //对于起点下面没有木板的情况
{
if(y > nmax)
return Inf;
else//不超过最大高度,直接下落
return y;
}
//起点下面有木板且距离第一块木板高度不超过max
ltime = y - p[i].h + x - p[i].lx;//从起点到i木板的左端的时间
rtime = y - p[i].h + p[i].rx - x;//从起点到i木板的右端的时间
//递归实现各木板到地的时间
if(leftmin[i] == -1)
leftmin[i] = mintime(i, 1);
if(rightmin[i] == -1)
rightmin[i] = mintime(i, 0);
ltime += leftmin[i];
rtime += rightmin[i];
if(ltime < rtime)//判断左边和右边的时间
{
return ltime;
}else
{
return rtime;
}
}
int main()
{
cin >> ncases;
while(ncases--)
{
cin >> n;
cin >> x >> y;
cin >> nmax;
//初始化左右两个数组都为-1
memset(leftmin, -1 , sizeof(leftmin));
memset(rightmin, -1, sizeof(rightmin));
//初始化平台为起始点
p[0].lx = x;
p[0].rx = x;
p[0].h = y;
//存储各平台
for(int i = 1; i <= n; ++i)
{
cin >> p[i].lx;
cin >> p[i].rx;
cin >> p[i].h;
}
//将各平台按高度由高到低排序
//qsort的原型 void qsort(void *base, int elem, int width, int(*fcmp)(const void *, const void *));
//参数:1.待排序数组首地址
//2.数组中排序元素数量
//3.各元素的占用空间大小
//4.指向函数的指针,确定排序的顺序
qsort(p, n + 1, sizeof(struct PlatForm), Compare);
cout << mintime(0, 1) << endl;
}
return 0;
}