跳房子

跳房子

题目

【题目描述】

跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一。跳房子的游戏规则如下:

在地面上确定一个起点,然后在起点右侧画n个格子,这些格子都在同一条直线上。每个格子内有一个数字(整数),表示到达这个 格子能得到的分数。玩家第一次从起点开始向右跳,跳到起点右侧的一个格子内。第二次再从当前位置继续向右跳,依此类推。规则规定:

玩家每次都必须跳到当前位置右侧的一个格子内。玩家可以在任意时刻结束游戏,获得的分数为曾经到达过的格子中的数字之和。

现在小 R 研发了一款弹跳机器人来参加这个游戏。但是这个机器人有一个非常严重的缺陷,它每次向右弹跳的距离只能为固定的 d 。小 R 希望改进他的机器人,如果他花 g 个金币改进他的机器人,那么他的机器人灵活性就能增加 gg ,但是需要注意的是,每 次弹跳的距离至少为1 。具体而言,当 g<d 时,他的机器人每次可以选择向右弹跳的距离为 d-g,d-g+1,d-g+2,dg,dg+1,dg+2 ,…, d+g-2d+g2 , d+g-1d+g1 , d+gd+g ;否则(当gd 时),他的机器人每次可以选择向右弹跳的距离为 1 , 2 , 3 ,…, d+g-2d+g2 , d+g-1d+g1 , d+gd+g 。

现在小 R 希望获得至少 k 分,请问他至少要花多少金币来改造他的机器人。

【输入格式】

第一行三个正整数 ndk,分别表示格子的数目,改进前机器人弹跳的固定距离,以及希望至少获得的分数。相邻两个数 之间用一个空格隔开。

接下来 n行,每行两个正整数xi,si,分别表示起点到第i个格子的距离以及第i个格子的分数。两个数之间用一个空格隔开。保证 xi 按递增顺序输入。

【输出格式】

共一行,一个整数,表示至少要花多少金币来改造他的机器人。若无论如何他都无法获得至少 k分,输出-1

【输入样例】

7 4 10
2 6
5 -3
10 3
11 -3
13 1
17 6
20 2

【输出样例】

2 

【样例解释】

2个金币改进后, 小 R 的机器人依次选择的向右弹跳的距离分别为2,3,5,3,4,3, 先后到达的位置分别为2,5,10,13,17,20, 对应1,2,3,5,6,7 这6 个格子。这些格子中的数字之和15 即为小 R 获得的分数。

【数据规模】

本题共 10 组测试数据,每组数据 10 分。

对于全部的数据满足1n500000,1d2000,1xi,k109,si<105。

对于第1,2组测试数据, n10;

对于第3,4,5 组测试数据, n500

对于第6,7,8 组测试数据, d=1

解析

这题本蒟蒻用了些玄学优化,不用二分,不用单调队列,O(n2)的dp居然过了。

好,说说思路:

首先既然是dp,那么肯定少不了状态:

令f[i]表示到达i格子的最大分数,初值为极小值,

状态转移方程:f[j]=f[i]+s[j],具体的i与j后面会说。

我们在读入的时候,先累加所有分数大于0的,如果maxn(maxn表示累加分数后的结果)小于k,那么直接输出-1,maxn记得开long long不然后5个点全部都会输出-1(说多了都是泪)!

反之我们从0开始累加g的值,即while循环。

每次我们从0到n-1枚举i,如果bj[i]为真(bj[i]表示能否到达i这个格子,初始全为false,由于g是累加的,所以如果之前的g可以到达i,那么之后的g必然也可以到达i,所以只需要初始化bj一次就可以了),

便从i+1到n枚举j,如果x[j]-x[i]<=d+g(x如题目所述),即从i到j的距离小于等于能够跳的最远距离,就判断如果x[j]-x[i]>=max(1,d-g),即从i到j的距离大于等于能过跳的最短距离,

就令bj[j]=true,f[j]=max(f[j],f[i]+s[j]),如果f[j]>=k,那么直接输出当前的g;

如果x[j]-x[i]>d+g,即从i到j的距离大于能够跳的最远距离,那么直接退出j循环,因为x是递增的,那么如果当前点跳不到,后面的点肯定也是跳不到的。

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;
int read()
{
    int num=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        num=(num<<1)+(num<<3)+ch-'0';
        ch=getchar();
    }
    return num*w;
}
int n,d,k,g,x[500100],s[500100],f[500100];
long long maxn;
bool bj[500100];
int main()
{
    memset(bj,false,sizeof(bj));
    memset(f,0xcfcfcfcf,sizeof(f));
    bj[0]=true,f[0]=0;
    n=read(),d=read(),k=read();
    for(int i=1;i<=n;i++)
    {
        x[i]=read(),s[i]=read();
        if(s[i]>0) maxn+=s[i];
    }
    if(maxn<k)
    {
        cout<<"-1";
        return 0;
    }
    while(1)
    {
        for(int i=0;i<n;i++)
            if(bj[i])
                for(int j=i+1;j<=n;j++)
                {
                    if(x[j]-x[i]<=d+g)
                    {
                        if(x[j]-x[i]>=max(1,d-g))
                        {
                            bj[j]=true;
                            f[j]=max(f[j],f[i]+s[j]);
                            if(f[j]>=k)
                            {
                                cout<<g;
                                return 0;
                            }
                        }
                    }
                    else break;
                }
        g++;
    }
    return 0;
}
View Code

转载于:https://www.cnblogs.com/I-Love-You-520/p/11410441.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript是一种脚本语言,常用于网页开发。在跳房子1游戏中,我们可以利用JavaScript实现玩家与电脑之间的互动和游戏逻辑。 首先,我们可以通过JavaScript来创建游戏的画布,并在画布上绘制游戏地图。游戏地图可以使用HTML的 \<canvas> 元素来创建,并使用JavaScript的绘图API来绘制不同的游戏元素,例如房子、玩家和障碍物。 接着,我们可以使用JavaScript来处理玩家的输入。通过监听玩家的键盘事件,我们可以实现玩家在游戏地图上移动的功能。当玩家按下相应的键时,JavaScript可以更新玩家角色的位置,并检查是否发生碰撞,比如玩家是否撞到了墙壁或障碍物。 在游戏逻辑方面,JavaScript可以实现跃的功能。我们可以使用JavaScript的定时器功能,在一段时间间隔内,让玩家角色在画布上跃。当玩家按下跃键时,JavaScript可以记录玩家的跃状态,并在每一帧更新玩家的垂直位置,使其看起来像是在地图上跃。 除此之外,我们还可以通过JavaScript来实现游戏的计分系统。当玩家成功过一个房子时,JavaScript可以更新玩家的得分,并将得分显示在游戏界面上。我们还可以在JavaScript中设定游戏结束的条件,比如玩家撞到墙壁或障碍物,当条件满足时,JavaScript可以展示玩家的最终得分并重置游戏。 通过以上的方式,我们可以用JavaScript实现跳房子1游戏,使玩家能够与游戏进行互动,并在游戏中体验到挑战和乐趣。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值