【数组】B066_NK_机器人跳跃问题(二分 / 递推)

一、Problem

机器人正在玩一个古老的基于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

二、Solution

方法一:二分

  • 规则:
    • 如果 E>hiE > h_i,跳上柱子 ii 机器人获得 EhiE - h_i 能量
    • 如果 E<hiE < h_i,跳上柱子 ii 机器人失去 EhiE - h_i 能量
    • 总结 E=E(hiE)=2×EhiE = E - (h_i - E) = 2 × E - h_i
  • 由题意得,某个区间 [l,r][l, r] 一定存在一个值 e 可以让机器人安全跳到终点,且这个值 e 越大越保险,基于这点,我们可以用二分来枚举这个区间 [l,r][l, r]
  • 怎么确定 r 呢?看数据范围…
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
	    int n, max = (int) 1e5 + 5, h[];
	    boolean check(int e) {
	        for (int i = 0; i < n; i++) {
	            e = 2 * e - h[i];
	            if (e >= max) return true;
	            if (e < 0)    return false;
	        }
	        return true;
	    }
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			n = sc.nextInt();
		    h = new int[n];
		    for (int i = 0; i < n; i++) h[i] = sc.nextInt();
		    int l = 0, r = 100000;
		    while (l < r) {
		        int mid = l + r >>> 1;
		        if (check(mid)) r = mid;
		        else            l = mid + 1;
		    }
		    System.out.println(r);
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

复杂度分析

  • 时间复杂度:O(logmax)O(log max)
  • 空间复杂度:O(1)O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章