Acwing 730. 机器人跳跃问题

Acwing 730. 机器人跳跃问题_第1张图片

Acwing 730. 机器人跳跃问题_第2张图片

 分析:题目要求最小值,先看看这道题是否可以用二分来做

(1)二分需满足二段性或单调性,本题中若E0满足要求,E0' >= E0是否也一定可以满足要求?

由题意可知,① 当H(k + 1) > E时,到达下一个位置的能量为 E - (H(k + 1) - E) = 2 * E - H(k + 1)

                     ② 当H(k + 1) <= E时,到达下一个位置的能量为 E + E - H(k + 1) = 2 * E - H(k + 1)

所以,所以下一个位置的能量表达式为2 * E - H(k + 1)

设E0为初始值,E1为跳到第一个位置后的能量,E2为跳到第二个位置后的能量...以此类推

若E0满足题目要求,则Ei >= 0, (i = 1, 2, 3, ....),若E0' >= E0,则Ei' >= 0

Acwing 730. 机器人跳跃问题_第3张图片

 说明Ei满足单调性,Acwing 730. 机器人跳跃问题_第4张图片

 (2)二分进行划分的条件怎么写,若if (check(mid))成立,说明初始能量为mid时,是可以满足要求的,如果mid可以满足要求,那么所有>= mid的位置一定可以满足要求,所以将r更新为mid,否则mid不满足要求,则将l更新为mid + 1。

注意,E(i + 1) = 2 * E(i) - H(k + 1),E(i + 1)在计算时有可能会爆int,所以我们进一步优化,看中间的值达到什么程度,一定会成功

假设我们中间所有建筑物的最大高度是maxH,如果说E在某个时刻已经大于等于maxH了,证明E一定是严格递增的,因此后面的所有E,都是严格>= 0的,可以直接返回true,这样可以防止中间过程爆掉。

Acwing 730. 机器人跳跃问题_第5张图片

 

#include 
#include 
#include 
#include 

using namespace std;

const int N = 100010;

int h[N];
int n;

// 判断是否满足条件
/*
如果初始值是这个能量e的话,中间的过程e'是否都是>= 0的
(这是我们的判断条件)
我们用这个条件判断,一定可以把答案二分出来
*/
bool check(int e)
{
    for (int i = 1; i <= n; ++ i)
    {
        e = e * 2 - h[i];
        if (e >= 2e5) return true;
        if (e < 0) return false;
    }
    return true;
}

int main()
{
    scanf("%d", &n);
    
    for (int i = 1; i <= n; ++ i) scanf("%d", &h[i]);
    
    int l = 0, r = 1e5;
    while (l < r)
    {
        int mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    
    printf("%d\n", l);
    
    return 0;
}

你可能感兴趣的:(二分与前缀和,蓝桥杯,c++,算法)