字节跳动春招真题,哪一年不知道。原题如下:
机器人跳跃问题
机器人正在玩一个古老的基于DOS的游戏。游戏中有N+1座建筑——从0到N编号,从左到右排列。编号为0的建筑高度为0个单位,编号为i的建筑的高度为H(i)个单位。
起初, 机器人在编号为0的建筑处。每一步,它跳到下一个(右边)建筑。假设机器人在第k个建筑,且它现在的能量值是E, 下一步它将跳到第个k+1建筑。它将会得到或者失去正比于与H(k+1)与E之差的能量。如果 H(k+1) > E 那么机器人就失去 H(k+1) - E 的能量值,否则它将得到 E - H(k+1) 的能量值。
游戏目标是到达第个N建筑,在这个过程中,能量值不能为负数个单位。现在的问题是机器人以多少能量值开始游戏,才可以保证成功完成游戏?
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32M,其他语言64M
输入描述:
第一行输入,表示一共有 N 组数据. 第二个是 N 个空格分隔的整数,H1, H2, H3, ..., Hn 代表建筑物的高度
输出描述:
输出一个单独的数表示完成游戏所需的最少单位的初始能量
示例1
输入例子:
5 3 4 3 2 4
输出例子:
4
示例2
输入例子:
3 4 4 4
输出例子:
4
示例3
输入例子:
3 1 6 4
输出例子:
3
本来这道题的做法很容易,但是有一些细节需要注意。首先就要意识到可能溢出的问题,为了防止溢出,将mid=(left+right)/2
写成mid=left+(right-left)/2
。但是光是这样还是不够,在计算的过程中x
可能会溢出,x
一旦大于等于Max
后面都不用再算肯定能走下去。这里的left
和right
的初始值也需要思考一下。代码如下:
#include <iostream>
#include<vector>
#include<limits.h>
#include<algorithm>
using namespace std;
int Max=0;
bool isEnough(vector<int>& h,int x){
for(int i=0;i<h.size();++i){
x=x+(x-h[i]);
// 为了防止溢出,可以直接在大于某个数时直接返回
if(x>=Max){
return true;
}
if(x<0){
return false;
}
}
return x>=0;
}
int main() {
int n;
cin>>n;
vector<int> h(n, 0);
int right=0;
for(int i=0;i<n;++i){
cin>>h[i];
right=max(right,h[i]);
}
Max=right;
int left=h[0]/2;
while(left<right){
int mid=left+(right-left)/2;
if(isEnough(h,mid)){
right=mid-1;
}
else{
left=mid+1;
}
}
if(isEnough(h,left)==false){
cout<<left+1<<endl;
}
else{
cout<<left<<endl;
}
}
// 64 位输出请用 printf("%lld")