Help Jimmy
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 1000000
int t,n,x,y,max;
struct Platform
{
int Lx,Rx,h;
};
Platform aPlatform[MAX_N+10]; //用于存放相关板的信息 Lx Rx 以及 h
int 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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
文章来源: recclay.blog.csdn.net,作者:ReCclay,版权归原作者所有,如需转载,请联系作者。
原文链接:recclay.blog.csdn.net/article/details/62045897
- 点赞
- 收藏
- 关注作者
评论(0)