OD_2024_C卷_200分_10、部门人力分配【JAVA】【二分法 + 双指针】

在这里插入图片描述

说明

输入数据两行,

第一行输入数据3表示开发时间要求,

第二行输入数据表示需求工作量大小,

输出数据一行,表示部门人力需求。

当选择人力为6时,2个需求量为3的工作可以在1个月里完成,其他2个工作各需要1个月完成。可以在3个月内完成所有需求。

当选择人力为5时,4个工作各需要1个月完成,一共需要4个月才能完成所有需求。

因此6是部门最小的人力需求。

代码

package odjava;

import java.util.Arrays;
import java.util.Scanner;

public class 十_部门人力分配 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int m = Integer.parseInt(sc.nextLine());
        int[] requirements = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        System.out.println(getResult(m, requirements));
    }

    public static long getResult(int m, int[] requirements) {
        Arrays.sort(requirements);

        int n = requirements.length;

        // 每辆自行车的限重 至少是 最重的那个人的体重
        long min = requirements[n - 1];
        // 每辆自行车的限重 至多是 最重的和次重的那两个的体重
        long max = requirements[n - 2] + requirements[n - 1];

        long ans = max;

        // 二分取中间值
        while (min <= max) {
            long mid = (min + max) >> 1; // 需要注意的是,min,max单独看都不超过int,但是二者相加会超过int,因此需要用long类型

            if (check(mid, m, requirements)) {
                // 如果mid限重,可以满足m辆车带走n个人,则mid就是一个可能解,但不一定是最优解
                ans = mid;
                // 继续尝试更小的限重,即缩小右边界
                max = mid - 1;
            } else {
                // 如果mid限重,不能满足m辆车带走n个人,则mid限重小了,我们应该尝试更大的限重,即扩大左边界
                min = mid + 1;
            }
        }

        return ans;
    }

    /**
     * @param limit        每辆自行车的限重
     * @param m            m辆自行车
     * @param requirements n个人的体重数组
     * @return m辆自行车,每辆限重limit的情况下,能否带走n个人
     */
    public static boolean check(long limit, int m, int[] requirements) {
        int l = 0; // 指向体重最轻的人
        int r = requirements.length - 1; // 指向体重最重的人

        // 需要的自行车数量
        int need = 0;

        while (l <= r) {
            // 如果最轻的人和最重的人可以共享一辆车,则l++,r--,
            // 否则最重的人只能单独坐一辆车,即仅r--
            if (requirements[l] + requirements[r] <= limit) {
                l++;
            }
            r--;
            // 用掉一辆车
            need++;
        }

        // 如果m >= need,当前有的自行车数量足够
        return m >= need;
    }
}
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值