Help Jimmy

来源:互联网 发布:网络语开挂是什么意思 编辑:程序博客网 时间:2024/05/17 23:20

Help Jimmy

四步走:

1.原问题分解为子问题

原问题:从最高点到地面所需要的时间
子问题:分为两个.从每个”相对”起点的左边走,或者从”相对结点的”右边走

2.确定状态

所谓的状态就是,各个路径沿途所经过的变量取值

在这个环境中对应起来就是, 各个路径中(从左边走||从右边走)沿途所经过变量(板子的编号)的取值

3.确定状态的边界值

边界不就是最后一行的取值(但是似乎这里不可深究太多,否则深陷递归的沼潭!)

4.确定状态的转移方程

假设从k 出发(看成点),k的正下方为m

LeftMinTime(k) = h(k) - h(m) + min(LeftMinTime(m)+ Lx(k)-Lx(m) +
RightMinTime(m)+Rx(m) - Rx(k) );

RightMinTime(k) = h(k) - h(m) + min(LeftMinTime(m)+Lx(k)-Lx(m) +
RightMinTime(m)+Rx(m) - Rx(k) );

再具体分析这个问题时就没那么麻烦了!
注:如果还实在理解不了,建议使用样例在IDE中单步执行,直至理解整个过程!

强调几个需要注意的事情:

1.首先要明确一件事,就是用户的标准输入的板子高度不是按照大小顺序排的,所以首先务必先把高度从高到低进行排序!
一下代码使用的是结构体排序用到cmp,如果不懂参参照另一篇博文:qsort理解

2.很明显每次都有两种选择可以使用,那么这时候就要有自己的主见了,
就是自己想怎样走一条路走到黑?(本例程是从左走到黑的)
这种思想颇像那个称硬币枚举那道题,可参见:称硬币

3.看代码注释

#include<stdio.h>#include<memory.h>#include<stdlib.h>#define MAX_N 1000#define INFINITE 1000000int t,n,x,y,max;struct Platform{    int Lx,Rx,h;};Platform aPlatform[MAX_N+10]; //用于存放相关板的信息 Lx Rx 以及 hint aLeftMinTime[MAX_N+10];  //记录某个板(看编号)的左端点是否走过int aRightMinTime[MAX_N+10]; //记录某个板(看编号)的右端点是否走过int MyCompare(const void *a,const void *b){    Platform *p1,*p2;    p1=(Platform *)a;    p2=(Platform *)b;    return p2->h-p1->h;//实现降序排列}int MinTime(int L,bool bLeft)//这里定义成bool类型更节省空间{    int y=aPlatform[L].h;//表示“相对”起点的高度(一块板的左右选相对起点)    int x,i;    if(bLeft)//假如这块板左边没当过“相对”起点,那就让他做“相对”起点!       x=aPlatform[L].Lx;    else        x=aPlatform[L].Rx;    for(i=L+1;i<=n;i++)//判断相对“起点”下的板是否能走,不能走的话就继续找下下块板,直到找到或没板!    {        if(aPlatform[i].Lx <= x && aPlatform[i].Rx >= x)//判断下一块板的左右端点是否在“相对”起点两侧,至少重合?            break;//在的话break掉    }    if(i<=n)//下一块板还存在    {        if( y - aPlatform[i].h > max )//判断是否会摔死            return INFINITE;    }    else//没板了    {        if( y > max )//这里容易写错,注意是y在比较!            return INFINITE;//摔死那就返回无穷大!        else            return y;//不会摔死返回高度差    }    int nLeftTime = y - aPlatform[i].h + x - aPlatform[i].Lx;//“相对”起点出发,从左所用时间    int nRightTime = y - aPlatform[i].h + aPlatform[i].Rx - x;//“相对”起点出发,从右所用时间    if( aLeftMinTime[i] == -1 )//这里的i已经自加,意即判断相对起点下的左端点是否做过“相对”起点?        aLeftMinTime[i] = MinTime(i, true);//没有的话继续让他作为“相对”起点。 这里容易写错注意走左边就是true!    if( aRightMinTime[i] == -1 )//同上,不过是右边        aRightMinTime[i] = MinTime(i, false);    nLeftTime += aLeftMinTime[i];//左边走的总时间    nRightTime += aRightMinTime[i];//右边走的总时间    if( nLeftTime < nRightTime )//返回最小值               return nLeftTime;    else        return nRightTime;}//其实仔细想想 aLeftMinTime[i]、aRightMinTime[i] 何尝不是最优子结构性质的体现呢?int main(){    int i,j;/*  freopen("in.txt","r",stdin);*/    scanf("%d", &t);    for( i = 0;i < t; i ++ )    {        memset(aLeftMinTime, -1, sizeof(aLeftMinTime));        memset(aRightMinTime, -1, sizeof(aRightMinTime));        scanf("%d%d%d%d", &n, &x, &y, &max);        aPlatform[0].Lx = x;        aPlatform[0].Rx = x;        aPlatform[0].h = y;        for(j = 1; j <= n; j ++ )            scanf("%d%d%d", & aPlatform[j].Lx, & aPlatform[j].Rx, & aPlatform[j].h);        qsort(aPlatform, n+1, sizeof(Platform), MyCompare);        printf("%d\n", MinTime(0, true));    }    return 0;}
0 0
原创粉丝点击