机器人跳跃问题 (二分)

时间:2022-07-28
本文章向大家介绍机器人跳跃问题 (二分),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题意描述

机器人正在玩一个古老的基于DOS的游戏。 游戏中有N+1座建筑——从0到N编号,从左到右排列。 编号为0的建筑高度为0个单位,编号为 i 的建筑高度为H(i)个单位。 起初,机器人在编号为0的建筑处。 每一步,它跳到下一个(右边)建筑。 假设机器人在第k个建筑,且它现在的能量值是E,下一步它将跳到第k+1个建筑。 如果H(k+1)>E,那么机器人就失去H(k+1)-E的能量值,否则它将得到E-H(k+1)的能量值。 游戏目标是到达第N个建筑,在这个过程中能量值不能为负数个单位。 现在的问题是机器人以多少能量值开始游戏,才可以保证成功完成游戏?

输入格式 第一行输入整数N。 第二行是N个空格分隔的整数,H(1),H(2),…,H(N)代表建筑物的高度。

输出格式 输出一个整数,表示所需的最少单位的初始能量值。

数据范围 1≤N,H(i)≤105,

输入样例1: 5 3 4 3 2 4 输出样例1: 4 输入样例2: 3 4 4 4 输出样例2: 4 输入样例3: 3 1 6 4 输出样例3: 3

思路

第一次做二分类型的题,完全没有思路,找不到满足的性质。 先来向大家分享一下整数二分的步骤:

整数二分的步骤: 1.找一个区间[L,R],使得答案一定在该区间中 2.找一个判断条件,使得该p判断条件具有二段性,并且答案一定是该二段性的分界点 3.分析终点M在该判断条件下是否成立,如果成立,考虑答案在哪个区间;如果不成立,考虑答案在哪个区间。 4.如果更新方式写的是R=mid,则不用做任何处理;如果更新方式写的是L=mid,则需要在计算mid时加1

那么我们来看这道题,首先找到一个区间。很明显,答案一定在[0,1e5]这个区间中。根据题意,如果h[k+1]>e,那么能量会损耗2e-h[k+1],如果h[k+1]<e,那么能量会增加2e-h[k+1],这时,题目所描述的两种情况就变成了一种。想要成功完成游戏,能量值在游戏的过程中就不能为负数,这就找到了一个性质。我们要找的就是满足这个性质的最小值。再来考虑一下,给定的能量区间中肯定存在一个最大的值,如果在某个时刻,能量值大于等于这个最大的能量,那么在之后的过程中就能量值肯定不可能为负数。接下来来考虑答案应该在哪个区间,如果满足了check程序,那么我们应该将R更新为mid。

AC代码

#include<iostream>
using namespace std;
const int N=1e5+10;
int h[N];
int n;
//判断是否满足该性质
bool check(int mid){
    for(int i=0;i<n;i++){
        mid=mid*2-h[i];
        if(mid>=1e5) return true;//不妨设最大值为1e5
        if(mid<0) return false;
    }
    return true;
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++) cin>>h[i];
    int l=0,r=1e5;
    while(l<r){
        int mid=l+r>>1;
        if(check(mid)) r=mid;//更新区间
        else l=mid+1;
    }
    cout<<l<<endl;
    return 0;
}