0 题目来源
1 涉及到的知识点
二分
一些技巧:
在遇到题目时,可以对各种算法(二分、dp、贪心等等)进行尝试,看哪种算法最为合适。
多考虑边界情况(最大数字、最小数字)
2 题目描述
机器人正在玩一个古老的基于 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个建筑,在这个过程中能量值不能为负数个单位。
现在的问题是机器人至少以多少能量值开始游戏,才可以保证成功完成游戏?
3 输入输出
输入格式:
第一行输入整数N。
第二行是N个空格分隔的整数,H(1),H(2),…,H(N)代表建筑物的高度。
输出格式:
输出一个整数,表示所需的最少单位的初始能量值上取整后的结果。
数据范围:
4 样例
输入样例1:
5
3 4 3 2 4
输出样例1:
4
输入样例2:
3
4 4 4
输出样例2:
4
输入样例3:
3
1 6 4
输出样例3:
3
5 思路
本题要求给定一个初始能量值E,使得从第一个建筑开始跳跃,跳到最后,能量仍然大于等于0。
明显,如果初始能量E非常大,则最后的能量一定大于0(符合条件);而如果初始能量E很小,则最后的能量很有可能小于0。即本题的条件具有二段性,我们要求的就是符合二段性的临界点的值,即符合最后剩余能量大于等于0的下界值。
根据上面的分析,我们可以使用binarysearch_lower_bound模板对问题进行解决。
根据分析,在从第i个建筑跳到第i+1个建筑时,能量。也即能量E几乎在翻倍(以的速度)增长,这样大的数据是不可能在int或者long long中存储的。观察可以看出,当E大于等于最高的建筑物时,E就不可能再减小了,此时的初始E一定符合条件。我们可以根据这个条件进行剪枝。
综上,本题可以使用二分法进行解决。
6 代码
#include<iostream>
#include<cstdio>
using namespace std;
int h[100010];
int n;
int maxn,minn=100001;
int binary_search_lower()
{
int l = 1, r = 100000;
int mid;
while (r > l)
{
mid = (l + r) / 2;
int e = mid;
int flag = 0;
for(int i=1;i<=n;i++)
{
e=2*e-h[i];
if(e<0)
{
flag=1;
break;
}
if(e>=maxn)//剪掉E>=max
{
flag=0;
break;
}
}
if (!flag)
r = mid;
else
l = mid + 1;
}
return l;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d", &h[i]);
if(h[i]>maxn)
maxn=h[i];
if(h[i]<minn)
minn=h[i];
}
cout << binary_search_lower();
return 0;
}