DP:poj1661 Help Jimmy

[转]http://blog.csdn.net/zxy_snow/article/details/5771229

 

此题目的“子问题”是什么呢?

n  Jimmy 跳到一块板上后,可以有两种选择,向左走或向右走。走到左端和走到右端所需的时间,容易算出。
n  如果我们能知道,以左端为起点到达地面的最短时间,和以右端为起点到达地面的最短时间,那么向左走还是向右走,就很容选择了。
n  因此,整个问题就被分解成两个子问题,即Jimmy 所在位置下方第一块板左端为起点到地面的最短时间,和右端为起点到地面的最短时间。这两个子问题在形式上和原问题是完全一致的。

 

 

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define INF 1000000
struct Platform
{
    int lx,rx,h;
}p[1010];    // 注意数组大小,要不会WA
int leftmin[1010];
int rightmin[1010];
int n,MAX;
int compare(const void * e1, const void * e2)//比较板高度,主函数中的快排要调用
{
    struct Platform * p1, * p2;
    p1 = (struct Platform * ) e1;  //C 的话 一定要写上struct 要不编译错误
    p2 = (struct Platform * ) e2;
    return p2->h - p1->h;
}
int mintime(int L,int flag)
{
    int y = p[L].h;
    int i,x,ltime,rtime;
    if( flag )
        x = p[L].lx;
    else
        x = p[L].rx;
    for(i=L+1; i<=n; i++)
    {
        if( p[i].lx<=x && p[i].rx>=x)
            break;
    }
    if( i<=n )
    {
        if( y - p[i].h > MAX )
            return INF;
    }
    else
    {
        if( y > MAX )
            return INF; 
        else 
            return y;//没有板子
    }
    ltime = y - p[i].h + x - p[i].lx;
    rtime = y - p[i].h - x + p[i].rx;
    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;
    }
}
/*********************************main*********************************/
int main(void)
{
    int i,ncases,x,y;
    scanf("%d",&ncases);
    while(ncases--)
    {
        scanf("%d %d %d %d",&n,&x,&y,&MAX);
        memset(leftmin,-1,sizeof(leftmin));
        memset(rightmin,-1,sizeof(rightmin));
        p[0].lx = x;
        p[0].rx = x;
        p[0].h = y;
        for(i=1; i<=n; i++)
            scanf("%d %d %d",&p[i].lx,&p[i].rx,&p[i].h);
        qsort( p,n+1,sizeof(struct Platform),compare );  //快排,按板子高度从高到低排
        printf("%d/n",mintime(0,1));   
    }
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值