
此题是一个最大化最小值的典型例题,
因为搜索范围是有界的,上界=最大木板长度+补充的全部木料长度,下界=最小木板长度;
即left=0,right=10^6;
我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功(补充的木料数<=m),说明还有继续上升的空间,那么就扩大x的范围(left=mid),否则就缩小范围(right=mid-1),直到搜索结束(left=right),此时left就是木板经过补充后的最小值。
java
public class Test15 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()) {
// 原木板长度
int n = scanner.nextInt();
// 要补充的木板长度
int m = scanner.nextInt();
int[] arr = new int[n];
for(int i =0;i<n;i++){
arr[i] = scanner.nextInt();
}
System.out.println(solution(arr, n, m));
}
}
private static int solution(int[] arr, int n, int m) {
int left = 0,right= (int)1e9;
while(left<right){
int mid = left + (right-left+1)/2;//向上取整,防止left=mid出现死循环
if(canReach(arr,mid,m)){
left = mid; // 可行,尝试更大值
}else{
right = mid - 1; // 不可行,缩小上界
}
}
return left;
}
private static boolean canReach(int[] arr, int mid,int m) {
long need = 0;
for(int a:arr){
if(a<mid){
need += mid -a;
}
}
return need<=m;
}
}