Help 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

分析:

对于每一块板都有向左和向右走两种情况。因此,求出向左时和向右时两种情况的时间。然后比较,并返回其中小的一个。
此题有点像装箱问题或是数字三角的简单变形。同样需要用一个数组来保存状态,否则会时间超限。本题本意上就是一个dp。

#include"stdio.h"
#include"string.h"
struct plat
{
    long long x;
    long long y;
    long long h;
} plth[1001],T;//这里是保存每个板块的基本信息的。
long long N,MAX;//N个数据,MAX表示不能超过的最大高度
long long minleft[1001];//表示第i块板往左走的最小时间。也是保存状态的
long long minright[1001];//表示第i块板往右走的最小时间。也是保存状态的

long long Mintime(long long l,long long bool1)//求最小时间函数
{
    long long x,y,i;
    long long Minlefttime;
    long long Minrighttime;
    if(bool1==1)//bool1值为1,则表示往左走
    {
        x=plth[l].x;
    }
    else
        x=plth[l].y;
  y=plth[l].h;//高度,y表示高度
  for(i=l+1;i<=N;i++)//循环找出来,第l块板的左边/右边的下方是哪一个块板
  {
      if(x>=plth[i].x&&x<=plth[i].y)
        break;
  }
  if(i<=N)//如果是提前退出的,则表示第i块板是下方板
  {
      if(y-plth[i].h>MAX)//看两板之间的距离,是否大于max,如果不大于 则先不处理
         return 10000000;
  }
  else//如果下方没板了。
  {
      if(y>MAX)//看此板与下方的距离是否大于max,大于 则返回无穷大
        return 10000000;
      else//否则返回y值即可
        return y;
  }
  //上述操作后,,仍未执行return的。 是满足下方有板,且板与板之间的高度为超过max。
Minlefttime=y-plth[i].h+x-plth[i].x;//将板与板之间的高度和到达下方板左边的距离相加,即是往左边走的时间,因为是1秒一米
Minrighttime=y-plth[i].h+plth[i].y-x;//同上
if(minleft[i]==-1)//如果==-1, 则证明之前未执行过此板,现在执行
   minleft[i]=Mintime(i,1)
if(minright[i]==-1)
   minright[i]=Mintime(i,0);
Minlefttime+=minleft[i];//将minleft[i]中的值表示此板往左边时最小的时间。加上到达此板的时间。即是总时间。
Minrighttime+=minright[i];//同上
if(Minlefttime<Minrighttime)//返回往左走和往右走的两者中小的那一个。 
    return Minlefttime;
else
    return Minrighttime;


}
int main()
{
    long long t,mintime;
    long long x,h,i,j;
    while(~scanf("%lld",&t))
    {
        while(t--)
        {   memset(minleft,-1,sizeof(minleft));
            memset(minright,-1,sizeof(minright));
            scanf("%lld%lld%lld%lld",&N,&x,&h,&MAX);
            plth[0].x=x;plth[0].y=x;plth[0].h=h;
            for(i=1;i<=N;i++)
            {
                scanf("%lld%lld%lld",&plth[i].x,&plth[i].y,&plth[i].h);

            }
            for(i=0;i<N;i++)
                for(j=i;j<=N;j++)
            {
                if(plth[i].h<plth[j].h)
                {
                    T=plth[i];
                    plth[i]=plth[j];
                    plth[j]=T;
                }
            }
         mintime=Mintime(0,1);
        printf("%lld\n",mintime);

        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43506138/article/details/84591850