题目
分析
看起来就是贪心+二分+剪枝,由于数据量很大 x<= 10^9
,肯定就不是模拟法了,直接贪心。
蛙蛙只需要管每次都跳最大步数的就行。
每次最大步数 1 <= y <= size
,所以在这里面进行二分。
剪枝是看需不需要模拟那么多次了,看数据规模肯定是不能模拟,其实无论是正向跳,还是逆向跳结果都一样(能跳就都能跳)。
直接跳满就完事。
代码
package com.maggot.maggotscheduler.bootstrap.utils.lanqiaobei13;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
/**
* @author huangyichun
*/
public class G青蛙过河 {
/**
* 看起来像是一个二分贪心+剪枝的算法。
* 蛙蛙只需要管每次都跳最大步数的就行
* 每次最大步数 1 <= y <= size,所以在这里面进行二分
* 剪枝是看需不需要模拟那么多次了,看数据规模肯定是不能模拟,其实无论是正向跳,还是逆向跳结果都一样(能跳就跳)
* 直接跳满就完事。
*/
public static void main(String[] args) {
System.out.println(getJump(2, 1, 0, 2, 0));
System.out.println(getJump(2, 1, 0, 1, 0));
System.out.println(getJump(2, 1, 0, 1, 0, 1, 1));
}
public static int getJump(int times, int... h) {
int max = h.length + 1;
int min = 0;
while (min < max) {
int step = (max + min) / 2;
if (testStep(times, step, h)) {
max = step;
} else {
min = step + 1;
}
}
return min;
}
public static boolean testStep(int times, int step, int[] h) {
int[] ints = Arrays.copyOf(h, h.length);
return dp(0, times, step, ints);
}
public static boolean dp(int position, int times, int step, int[] ints) {
Queue<JumpWay> queue = new ArrayDeque<>();
for (int i = position + step; i >= position && times != 0; i--) {
if (i >= ints.length) {
times = 0;
break;
}
int thisTimesJump = Math.min(ints[i], times);
times -= thisTimesJump;
ints[i] -= thisTimesJump;
queue.add(new JumpWay(thisTimesJump, i));
}
if (times != 0) {
return false;
}
while (!queue.isEmpty()) {
JumpWay poll = queue.poll();
if (!dp(poll.position, poll.times, step, ints)) {
return false;
}
}
return true;
}
static class JumpWay {
int times = 0;
int position = 0;
public JumpWay(int times, int position) {
this.times = times;
this.position = position;
}
}
}