华为OD题目:不爱施肥的小布

华为OD题目:不爱施肥的小布

题目描述:
某农场主管理了一大片果园,felds[i] 表示不同果林的面积,单位m^2),现在要为所有的果林施肥且必须在 n 天之内完成,否则景响收成。
小布是果林的工作人员,他每次选择一片果林进行施肥,且一片果林施肥完后当天不再进行施肥作业,假设施肥机的能效为k,单位:(m^2/day),
请问至少租赁能效 k 为多少的施肥机才能确保不影响收成? 如果无法完成施肥任务,则返回 -1.

输入描述:
第一行输入为 m和n,m 表示 fields 中的元素个数,n 表示施肥任务必须在n天内 (含n天) 完成
第二行输入为 fields,fields[i] 表示果林的面积,单位:(m“2)
输出描述:
对于每组数据,输出最小施肥机的能效 k,无多余空格。
补充说明:
1 <= fields.length <= 10^4
1 <=n e= 10^9
1 <= fieldslil <= 10^9

示例1
输入:
5 7
5 7 9 15 18
输出:
0
说明:
当能效K为9时,feldsl0 需要1天, felds[1] 需要1天, felds[2] 需要1天, felds[3] 需要2天,felds[4] 需要2天,共需要7天,不会影响收成。

示例2
输入:
3 1
2 3 4
输出:
说明:
由于一天最多完成一片果林的施肥,无论 k 为多少都至少需要3天才能完成施肥,因此返回-1。

解题思路:
我们可以将施肥的过程看作是在一条时间轴上不断“拼接”若干个长度为 fields[i]/k 的工作日,题目的要求就是要找到最小的 k,使得这些工作日总数不超过 n。显然,k 越大,每个工作日的长度越短,所以总数就越多;k 越小,则工作日的长度越长,因此总数就越少。

因此,我们可以使用二分查找来快速定位最小的合适的 k。具体地,假设当前二分的区间为 [l, r],我们先计算出 mid = (l+r) // 2。接着,我们模拟施肥机以 k=mid 的能效完成施肥任务需要的天数 cnt,并与给定的 n 进行比较:

  • 如果 cnt <= n,表示以 k=mid 的能效可以在规定天数内完成所有的施肥任务,因此我们继续在区间 [mid+1, r] 中寻找更小的 k;

  • 如果 cnt > n,表示以 k=mid 的能效无法在规定天数内完成所有的施肥任务,因此我们需要在区间 [l, mid-1] 中寻找更大的 k。

不断重复以上过程,直到确定最小的合适的 k 为止。最终,我们返回的结果即为最小的合适的 k。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        String[] strings = str.split(" ");
        int m = Integer.parseInt(strings[0]);
        int n = Integer.parseInt(strings[1]);

        String line = sc.nextLine();
        String[] split = line.split(" ");
        int[] nums = new int[split.length];
        int max = 0;
        for (int i = 0; i < split.length; i++) {
            int num = Integer.parseInt(split[i]);
            max = Math.max(num, max);
            nums[i] = num;
        }

        int left = 1;
        int right = max;
        while (left < right) {
            int mid = (right + left) / 2;
            //看中间值的速度,需要的天数是否超过n
            if (getDays(mid, nums) > n) {
                //如果超过n了,不满足条件,那么说明速度要加快,
                left = mid + 1;
            } else {
                right = mid;
            }
        }

        //如果取最终的left,算出的天数还是大于n,返回-1, 否则结果为left
        if (getDays(left, nums) > n) {
            System.out.println(-1);
        } else {
            System.out.println(left);
        }


    }

    //获取天数,注意这里是向上取整
    public static int getDays(int speed, int[] nums) {
        int dayNum = 0;
        for (int num : nums) {
            //如果刚好是速度的倍数,则加上val,否则再+1
            if (num % speed == 0) {
                dayNum += num / speed;
            } else {
                dayNum += num / speed + 1;
            }
        }

        return dayNum;
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值