机器人正在玩一个古老的基于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
题目大概说了个什么意思呢,前面有不同高度的楼,机器人开始从当前位置跳跃,自身有一个能量值,每次跳跃的时候会进行判断
如果目前“能量>高度”
那么跳跃之后的能量值就变成了(能量 + (能量 - 高度))
如果目前“能量<高度”
那么跳跃之后的能量值就变成了(能量 - (高度 - 能量))
看起来跟楼层高度差好像没什么关系,不是平常的爬几层消耗几格能量,一开始还挺懵逼的,高中的时候数学老师告诉我,不管会不会,别光看,动笔算一算,看看自己到底是死在哪,于是设当前的能量是E推算一下
举个栗子
用测试数据3 4 3 2 4来举例,当前在第一个位置,能量是E,那么跳下一个位置以后的能量,有两种可能,一种是E < 4;一种是E > 4
但是最后的结果都是2E - 4;于是乎发现了每一次跳跃之后,能量都会变成2E - H
有了这个结论就好说了,数据范围给的是0 ~ 100000;我们用二分法来找到最合适的那个数据值,每次找到一个之后,就推算一遍看看这个能量值能不能跳到最后(跳到最后的条件就是能量值不会为负数)。代码如下:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int N = 100010; int q[N]; //这个函数用来判断当前的能量值能不能跳到最后,最终返回值也是看正数还是负数 int get(long long e, int len) { for(int i = 0 ; i < len ; i++) { if(e - q[i] > 100000) return 1; e = 2 * e - q[i]; if(e < 0) return e; } return 1; } int main() { int n; cin >> n; for(int i = 0 ; i < n ; i ++ ) scanf("%d", &q[i]); int l = 0, r = 100000; while(l < r)//二分查找能量值 { long long mid = l + r >> 1; if(get(mid, n) > 0) r = mid; else l = mid + 1; } cout << l << endl; return 0; }
注: 因为能量值最初也是会从50000开始,如果数据楼层比较低的地方,那么他不断的叠加能量,就会爆int,long long也会爆,就会出现能量太多导致负数的情况,所以在get函数中增加一个判断,如果当前的能量远大于楼层的高度,就直接return了
还有一点,因为最后我们要的是大于0的哪一个结果,所以判断条件用的是 ">0"