M - Help Jimmy(动态规划+贪心)

题目
“Help Jimmy” 是在下图所示的场景上完成的游戏。
在这里插入图片描述
场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

设计一个程序,计算Jimmy到底地面时可能的最早时间。

输入
第一行是测试数据的组数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恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。

输出
对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。

样例输入

1
3 8 17 20
0 10 8
0 10 13
4 14 3

样例输出

23

思路
这道题一开始的时候其实我没太看懂输入,有点绕。
输入第一行的n,x,y,h分别对应有几个台阶,你当前处于的x位置,你当前处于的高度和你每次往下跳不能超过的高度。

首先我们在存储完所有的台阶之后,我们把自己所处的台阶(比较特别,x1=x2=x)和地面(也是比较特别,x1,x2都是无限大,h=0)也存在数组中。

struct node
{
    int x1,x2,h;
} a[1100];

scanf("%d%d%d%d",&n,&x,&y,&maxh);

for(int i=1; i<=n; i++)
    scanf("%d%d%d",&a[i].x1,&a[i].x2,&a[i].h);
    
a[n+1].x1=x;
a[n+1].x2=x;
a[n+1].h=y;    //起点台阶的信息
a[0].x1=-2e6;
a[0].x2=2e6;
a[0].h=0;      //地面的信息

然后我们将信息按高度从低到高排个序:

bool cmp(node b1,node b2)
{
    return b1.h<b2.h;
}

sort(a,a+n+2,cmp);  //一共有n+1个元素

接下来我们设计一个数组dp[1100][2]。
dp[i][0]的值为从第i层向左走到达地面的最短时间,dp[i][1]的值为从第i层向右走到达地面的最短时间。
接下来我们从第2层开始,算出每层向左走到达地面的最短时间和向右走的最短时间。

最后我们取dp[n+1][0]和dp[n+1][1]两者中较小值就ok了(贪心)。

直接看代码,伊丽莎白!
在这里插入图片描述
代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

struct node
{
    int x1,x2,h;
} a[1100];

int n,x,y,maxh;
int dp[1100][2];

bool cmp(node b1,node b2)
{
    return b1.h<b2.h;
}

void Leftmin(int m)   //求第m层向左走到地面的最少时间
{
    int k=m-1;        //向下一层出发
    while(k>0&&a[m].h-a[k].h<=maxh)  //如果没到地面,并且允许我们跳下去
    {
        if(a[m].x1>=a[k].x1&&a[m].x1<=a[k].x2)   //看一下能不能安全落地
        {
            dp[m][0]=a[m].h-a[k].h+min(a[m].x1-a[k].x1+dp[k][0],a[k].x2-a[m].x1+dp[k][1]);   //落地之后选择向左还是向右继续走
            return ;
        }
        else
            k--;
    }
    if(a[m].h-a[k].h>maxh)  //如果不可以直接跳到地面
        dp[m][0]=2e6;
    else                    //如果可以直接跳到地面
        dp[m][0]=a[m].h;    //信仰之跃
}
void Rightmin(int m)   //求第m层向右走到地面的最少时间,一样的过程
{
    int k=m-1;     
    while(k>0&&a[m].h-a[k].h<=maxh)
    {
        if(a[m].x2<=a[k].x2&&a[m].x2>=a[k].x1)
        {
            dp[m][1]=a[m].h-a[k].h+min(a[m].x2-a[k].x1+dp[k][0],a[k].x2-a[m].x2+dp[k][1]);  //同样考虑向哪边走
            return ;
        }
        else
            k--;
    }
    if(a[m].h-a[k].h>maxh)
        dp[m][1]=2e6;
    else
        dp[m][1]=a[m].h;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d",&n,&x,&y,&maxh);
        for(int i=1; i<=n; i++)
            scanf("%d%d%d",&a[i].x1,&a[i].x2,&a[i].h);
        a[n+1].x1=x;
        a[n+1].x2=x;
        a[n+1].h=y;
        a[0].x1=-2e6;
        a[0].x2=2e6;
        a[0].h=0;
        sort(a,a+n+2,cmp);
        for(int i=1; i<=n+1; i++)
        {
            Leftmin(i);
            Rightmin(i);
        }
        cout<<min(dp[n+1][0],dp[n+1][1])<<endl;  //最后贪一下(●'◡'●)
    }
}

虽然只是蓝桥国三,但还是很开心o( ̄▽ ̄)ブ

在这里插入图片描述
继续努力,下次再见~

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
use java language ,In this project you need to write a book lending system for a Library. The system has different roles for registered users. There are two types of user roles: borrower and lender. Write an IUser interface for library users, with the following UML specification: +----------------------------------+ | <<interface>> | | IUser | +----------------------------------+ | + getName(): String | | + getBook(): int | | + moreBook(int number): void | +----------------------------------+ and a User class that implements IUser and has the following UML specification: +-----------------------------------+ | User | +-----------------------------------+ | - name: String | | - book: int | +-----------------------------------+ | + User(String name, int book) | | + getName(): String | | + getBook(): int | | # setBook(int book): void | | + moreBook(int number): void | | + testUser(): void | +-----------------------------------+ The name instance variable indicates the user name. The book instance variable indicates the number of books borrowed by the user. The setBook method changes the number of books borrowed by the user. The setBook method is protected, not public. This means that only subclasses of the User class can use the setBook method. All the other classes in the system cannot use the setBook method, so they cannot change the number of books borrowed by a user. The purpose of the moreBook method is to increase the number of books borrowed or lent by the user (depending on what kind of user it is) by the number given as argument to the method. The moreBook method of the User class is abstract, since we do not know what kind of role the user is (a borrower borrows books from other users and a lender lend books to other users). Also add to your program a Test class to test your User class. public class Test { public static void main(String[] args) { User.testUser(); } }
最新发布
05-25

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值