题目搬运自:[AcWing 今日头条2019笔试题](https://www.acwing.com/problem/content/732/)
题目描述
机器人正在玩一个古老的基于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
看到这种题,首先不要多想,要动笔推一下。
如果h > E,那么 E = E - (h - E) = 2E - h,
否则 E = E + E - h = 2E - h。
此外,还要注意一下在 check 中溢出的问题,我们知道h有最大值,而且能满足条件的 e 是会不断递增的,所以在函数中写一个特判,当e > 1e5 时,以后的h一定都会跨过去 。 比如e = 1e5+1,即便后边遇到的h都是1e5,e还剩下1e5+2···依次下去,不断递增。
AC代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;
// 除了动脑还要多动笔 推公式
const int MAXN = 1e5 + 10;
int n, h[MAXN];
bool check(LL e) {
int flag = 1;
for(int i = 1; i <= n; i++) {
if(e > 100000) return true;
// 巧妙的地方
// 因为满足条件的e是严格递增的 所以判断一下e是否大于maxh即可
e = 2 * e - h[i];
if(e < 0) {
return false;
}
}
return flag;
}
int main() {
cin >> n;
for(int i = 1; i <= n; i++) {
scanf("%d", &h[i]);
}
int l = 1, r = 1e5, mid;
while(l < r) {
mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l << endl;
return 0;
}