POJ1661Help Jimmy(动态规划)

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

思路:

关键:运用递归的思想用动态规划的数组实现

方法:将输入的数据按高度由高到底排序,然后从最高一个向下递归,根据条件判断做出相应的动作,利用数组存储相应的时间

实现考虑:
1.不妨认为Jimmy开始的位置是一个编号为0,长度为0的板子,那么整个问题就是要求LeftMinTime(0)。
2. 输入数据中,板子并没有按高度排序,所以程序中一定要首先将板子排序。
3. LeftMinTime(k)和RightMinTime(k)可以用同一个过程来实现(用一个布尔变量来区分)此处程序用的Flag

#include 
#include 
#include 
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;
}


 

你可能感兴趣的:(OJ)