why

求最小/最大都第一时间想到二分(二分- dfs - dp - 贪心),具有“单调性“的题目都可以用二分来做,那我们考证一下E0‘>E0,E0可以完成任务,E0‘是否也可以成功完成,如果是那么它就是一个单调递增的。经过下图分析,很明显这道题是训练二分的一道好题。
image.png

how

读题

  • 有i个城堡,城堡高度从0 ~ i排布(从低到高)
  • 机器人从0开始不断跳跃,而且机器人存在能量值E,跳跃会消耗机器人的能量
  • 如果城堡高度H(i+1)> E ,损失H - E,否则 增加E-H(也就是机器人往比它能量高的城堡高度条,会损失能量。往比它能量低的城堡跳会获得能量,计算公式就是大 减去小)

问:需要多少能量机器人才能跳完所有城堡
ps:经过数据转换得到一个公式,2E-h。
image.png

思路

1.取一个相对大的范围,暴力夹击(每次取中间值,然后将暴力区域不断划分到数组左右两边),每轮的中间值都拿去跑所有塔。
2.只要机器人不死就是true,死了(E<0)false,
3.还有一种溢出情况需要考虑,如果这个中间值非常大了,在跑塔过程中可能会爆掉int内存,既然它能量非常大了也没必要进行跑塔了,直接让它通过。

代码

  1. import java.util.Scanner;
  2. public class robot {
  3. static int[] nums;
  4. public static boolean check(int e) {
  5. for (int i = 0; i < nums.length; i++) {
  6. e = 2 * e - nums[i];
  7. if (e >= 100010) {
  8. return true;
  9. }
  10. if (e < 0) {
  11. return false;
  12. }
  13. }
  14. return true;
  15. }
  16. public static void main(String[] args) {
  17. Scanner sc = new Scanner(System.in);
  18. int numsLength = sc.nextInt();
  19. nums = new int[numsLength];
  20. for (int i = 0; i < numsLength; i++) {
  21. nums[i] = sc.nextInt();
  22. }
  23. int left = 0;
  24. int right = 100010;
  25. while (left < right) {
  26. int middle = (left + right) / 2;
  27. if (check(middle)) {
  28. right = middle;
  29. }else{
  30. left = middle+1;
  31. }
  32. }
  33. System.out.println(left);
  34. }
  35. }