机器人跳跃问题
题目描述
题意解释
核心思路
根据题意可知:
- 当 H ( k + 1 ) > E H(k+1)>E H(k+1)>E时,则要损失 H ( k + 1 ) − E H(k+1)-E H(k+1)−E的能量,那么此时的能量为 E − ( H ( k − 1 ) − E ) = 2 E − H ( k + 1 ) E-(H(k-1)-E)=2E-H(k+1) E−(H(k−1)−E)=2E−H(k+1)。
- 当 H ( k + 1 ) ≤ E H(k+1)\leq E H(k+1)≤E时,则要得到 E − H ( k + 1 ) E-H(k+1) E−H(k+1)的能量,那么此时的能量为 E + ( E − H ( k + 1 ) ) = 2 E − H ( k + 1 ) E+(E-H(k+1))=2E-H(k+1) E+(E−H(k+1))=2E−H(k+1)。
于是我们发现这两种情况都会得到相同的值 2 E − H ( k + 1 ) 2E-H(k+1) 2E−H(k+1)。
问题:假设我们找到了某个初始能量 E 0 E_0 E0是满足要求的。然后已知 E 0 ′ > E 0 E_0'>E_0 E0′>E0,那么初始能量 E 0 ′ E_0' E0′是否也满足要求呢?
答案是肯定的。证明如下: 假设有3个建筑。公式 2 E − H [ k + 1 ] 2E-H[k+1] 2E−H[k+1]
对于初始能量 E 0 E_0 E0来说,第一个建筑的能量为 E 1 = 2 E 0 − H [ 1 ] E_1=2E_0-H[1] E1=2E0−H[1],第二个建筑的能量为 E 2 = 2 E 1 − H [ 2 ] E_2=2E_1-H[2] E2=2E1−H[2],第三个建筑的能量为 E 3 = 2 E 2 − H [ 3 ] E_3=2E_2-H[3] E3=2E2−H[3]。
对于初始能量 E 0 ′ E_0' E0′来说,第一个建筑的能量为 E 1 ′ = 2 E 0 ′ − H [ 1 ] E_1'=2E_0'-H[1] E1′=2E0′−H[1],第二个建筑的能量为 E 2 ′ = 2 E 1 ′ − H [ 2 ] E_2'=2E_1'-H[2] E2′=2E1′−H[2],第三个建筑的能量为 E 3 ′ = 2 E 2 ′ − H [ 3 ] E_3'=2E_2'-H[3] E3′=2E2′−H[3]。因为 E 0 ′ > E 0 E_0'>E_0 E0′>E0,因此有 E 1 ′ > E 1 E_1'>E_1 E1′>E1,于是有 E 2 ′ > E 2 E_2'>E_2 E2′>E2,接着有 E 3 ′ > E 3 E_3'>E_3 E3′>E3。运用数学归纳法可知, E i ′ > E i E_i'>E_i Ei′>Ei, ⋯ \cdots ⋯, E n ′ > E n E_n'>E_n En′>En。
因此,证明了只要找到某个初始能量 E 0 E_0 E0是满足要求的,那么所有大于等于 E 0 E_0 E0的能量也是满足要求的。
这样,我们就知道了它是有单调性的,即 ≥ E 0 \geq E_0 ≥E0都满足, < E 0 <E_0 <E0都不满足。只要具有了单调性,就一定可以用二分算法来做。但是能用二分法来做并不一定需要具有单调性,二分算法的本质是二段性而不是单调性。
设这些建筑中最大的高度为 M a x H MaxH MaxH, M a x H > 0 MaxH>0 MaxH>0,设某一时刻的能量 E i ≥ M a x H E_i\geq MaxH Ei≥MaxH, E i > 0 E_i>0 Ei>0,那么下一个能量 E i + 1 = 2 E i − h [ i + 1 ] E_{i+1}=2E_i-h[i+1] Ei+1=2Ei−h[i+1],即 E i + 1 = E i + E i − h [ i + 1 ] ≥ E i + ( M a x H − h [ i + 1 ] ) E_{i+1}=E_i+E_i-h[i+1]\geq E_i+(MaxH-h[i+1]) Ei+1=Ei+Ei−h[i+1]≥Ei+(MaxH−h[i+1]),由于 M a x H ≥ h [ i + 1 ] MaxH\geq h[i+1] MaxH≥h[i+1],所以 M a x H − h [ i + 1 ] ≥ 0 MaxH-h[i+1]\geq 0 MaxH−h[i+1]≥0,也就有 E i + 1 ≥ E i E_{i+1}\geq E_i Ei+1≥Ei,而 E i > 0 E_i>0 Ei>0,所以有 E i + 1 > 0 E_{i+1}>0 Ei+1>0,也就是 E i + 1 − E i ≥ 0 E_{i+1}-E_i\geq 0 Ei+1−Ei≥0,也就是说,当出现 E = = M a x H E==MaxH E==MaxH了,那么后面的能量就都是递增的了,而不会是递减。既然能保证后面的能量是>0的,而不是负数,那么就是满足题目要求的,那么也就没有必要去算 E E E后面的了。之所以这么想,就是因为 2 ∗ E − h 2*E-h 2∗E−h,由于是相乘,如果 h h h很小,那么可能由于相乘的结果很大而爆long long。因此,我们需要作出这种优化来规避爆long long。
问题:如何理解二分的右范围是1e5呢?
题目说了建筑物最大是1e5。由上面我们证明了,当某个时刻 E = = M a x H E==MaxH E==MaxH后,能量就是递增的,后面的一定都是答案,但是在还没有碰到 E = = M a x H E==MaxH E==MaxH前,有可能会出现答案。也就是说很不幸的是,有个建筑物的高度是1e5,然后只有当 E = 1 e 5 E=1e5 E=1e5时,我们才能保证1e5以上的都是答案,我们肯定知道1e5以上的都是答案了,因此1e5以上的就没有必要去二分了。由于是求最小的初始能量,所以只需要在区间 [ 1 , 1 e 5 ] [1,1e5] [1,1e5]之间找就行了。而且这个区间中的答案一定比1e5以上区间的答案还要是最优解。(因为有单调性)
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int n;
int h[N]; //存储所有建筑物的高度
int maxH=0; //记录这些建筑物中的最大的那个高度
//判断某个点e是否满足 "大于等于E0" 的这个性质
bool check(int e)
{
for(int i=1;i<=n;i++)
{
//公式
e=e*2-h[i];
//当某一个时刻出现e>=maxH,则后面的所有能量就都是满足要求的,都是答案
if(e>=maxH)
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]);
maxH=max(maxH,h[i]);
}
//所需的最少的初始能量的范围是[1,1e5] 1e5以上的肯定都是答案,但不是最小的
int l=0,r=1e5;
//二分找到 大于等于某个东西的最小值 即最大值的最小 即左侧边界
//由于证明了有单调性,那么一定可以用二分
while(l<r)
{
int mid=l+r>>1;
if(check(mid))
r=mid;
else
l=mid+1;
}
//退出while循环后的l和r就是答案
printf("%lld\n",l);
return 0;
}