全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:不爱施肥的小布
知识点二分查找
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
某农场主管理了一大片果园,fields[i] 表示不同果林的面积,单位:(m^2),现在要为所有的果林施肥且必须在 n 天之内完成,否则影响收成。小布是果林的工作人员,他每次选择一片果林进行施肥,且一片果林施肥完后当天不再进行施肥作业。假设施肥机的能效为k,单位:(m^2/day),请问至少租赁能效 k 为多少的施肥机才能确保不影响收成?如果无法完成施肥任务,则返回 -1。
输入描述:
第一行输入为 m 和 n,m 表示 fields 中的元素个数,n 表示施肥任务必须在 n 天内(含 n 天)完成;
第二行输入为 fields,fields[i] 表示果林i的面积,单位:(m^2)
输出描述:
对于每组数据,输出最小施肥机的能效 k,无多余空格。
补充说明:
1 <= fields.length <= 10^4
1 <= n <= 10^9
1 <= fields[i] <= 10^9
示例1
输入:
5 7
5 7 9 15 10
输出:
9
说明:
当能效k为9时,fields[0] 需要1天,fields[1] 需要1天,fields[2] 需要1天,fields[3] 需要2天,fields[4] 需要2天,共需要7天,不会影响收成。
示例2
输入:
3 1
2 3 4
输出:
-1
说明:
由于一天最多完成一片果林的施肥,无论 k 为多少都至少需要3天才能完成施肥,因此返回-1。
解题思路:
使用二分法。
获取最低能效l=1,获取最高能效(面积最大的果林)r=max
先取中间值mid =(l+r)/2,判断mid是否满足条件。
满足条件判断:ans为需要的天数。
遍历林园面积除以mid,若能整除则ans += 面积/mid,若不能整除,则ans += 面积/mid + 1;若ans<=m(规定天数),则满足,反之不满足。
若mid满足,则r=mid;如不满足,则l=mid+1;继续mid=(l+r)/2进行判断。以此类推,直至l>=r。
代码实现一:
package com.codernav.demo.hwod.exam;
import java.util.Arrays;
import java.util.Scanner;
/**
* @title 不爱施肥的小布
* @Description 某农场主管理了一大片果园,fields[i] 表示不同果林的面积,单位:(m^2),现在要为所有的果林施肥且必须在 n 天之内完成,否则影响收成。
* 小布是果林的工作人员,他每次选择一片果林进行施肥,且一片果林施肥完后当天不再进行施肥作业。
* 假设施肥机的能效为k,单位:(m^2/day),请问至少租赁能效 k 为多少的施肥机才能确保不影响收成?如果无法完成施肥任务,则返回 -1。
* @Author 开发者导航
* @website https://codernav.com
* @date 2023/5/14
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[] fields = new int[m];
for (int i = 0; i < m; i++) {
fields[i] = sc.nextInt();
}
int l = 1; //最低能效
int r = Arrays.stream(fields).max().getAsInt(); //最高能效
while (l < r) {
int mid = (l + r) / 2; //取中位数
if (check(mid, fields) <= n) { //判断能效施肥满足天数要求
r = mid; //满足要求,右边界缩小
} else {
l = mid + 1; //不满足,左边界缩小
}
}
if (check(l, fields) > n) {
System.out.println(-1);
} else {
System.out.println(l);
}
}
/**
* 判断mid能效需要几天完成施肥
*
* @param mid 能效
* @param fields 面积数组
* @return
*/
public static int check(int mid, int[] fields) {
int ans = 0;
for (int i = 0; i < fields.length; i++) {
if (fields[i] % mid == 0) { //能整除能效则直接添加,否则需要+1
ans += fields[i] / mid;
} else {
ans += fields[i] / mid + 1;
}
}
return ans;
}
}
