题十二:部门人力分布

题目描述
部门在进行需求开发时需要进行人力安排。 当前部门需要完成 N 个需求,需求用 requirements 表述,requirements[i] 表示第 i 个需求的工作量大小,单位:人月。 这部分需求需要在 M 个月内完成开发,进行人力安排后每个月人力时固定的。 目前要求每个月最多有2个需求开发,并且每个月需要完成的需求不能超过部门人力。 请帮助部门评估在满足需求开发进度的情况下,每个月需要的最小人力是多少?

输入描述
输入为 M 和 requirements,M 表示需求开发时间要求,requirements 表示每个需求工作量大小,N 为 requirements长度,
1 ≤ N/2 ≤ M ≤ N ≤ 10000
1 ≤ requirements[i] ≤ 10^9

输出描述
对于每一组测试数据,输出部门需要人力需求,行末无多余的空格

用例:
3
3 5 3 4
6
说明:
输入数据两行,
第一行输入数据3表示开发时间要求,
第二行输入数据表示需求工作量大小,
输出数据一行,表示部门人力需求。
当选择人力为6时,2个需求量为3的工作可以在1个月里完成,其他2个工作各需要1个月完成。可以在3个月内完成所有需求。
当选择人力为5时,4个工作各需要1个月完成,一共需要4个月才能完成所有需求。 因此6是部门最小的人力需求。

思路
题目描述了一个关于人力资源规划的问题。具体来说,有以下要点:
1. 需求开发任务:存在 N 个需求开发任务,每个任务的工作量用一个数组 requirements 来表示,其中 requirements[i] 是第 i 个需求的工作量。
2. 时间限制:所有的需求必须在 M 个月内完成。
3. 人力安排:每个月的人力是固定的,并且每个月最多只能开发两个需求。
4. 人力限制:每个月完成的需求工作量总和不能超过可用的人力。 题目要求计算在满足上述条件的情况下,每个月所需的最小人力是多少。

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

public class Main {

    public static void main(String[] args) {
        //创建Scanner对象读取输入
        Scanner sc = new Scanner(System.in);
        //读取第一行输入,表示需求开发时间要求
        int m = Integer.parseInt(sc.nextLine());
        //读取第二行输入,表示每个需求的工作量大小,并转换为整数数组

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

        //对需求工作量进行排序
        Arrays.sort(requirements);
        //初始化二分查找的左边界为最大工作需求量
        int left = requirements[requirements.length -1 ];
        //初始化二分查找右边界所有需求工作量之和除以最小月数 +1
        int right = Arrays.stream(requirements).sum()/(m/2) + 1;
        //进行二分查找以确定最小人力
        while(left < right){
            //计算中间值
            int mid = left + (right - left)/2;
            //初始化所需月数
            int monthsNeeded = 0;
            //遍历每个需求,判断是否可以在限定人力下完成
            for(int i = requirements.length -1 ,j=0;i>=j;--i){
                //如果当前需求大于中间人力值,则增加左边界
                 if(requirements[i]>mid){
                     left = mid+1;
                     break;
                 }
                 //如果当前和下一个需求只和大于中间人力值,或者只剩一个需求,则增加所需月数
                if(i==j|| requirements[i] + requirements[j]>mid){
                    monthsNeeded++;

                }else {
                    //否则,将下一个需求也计算在当月份内,并增加所需月数
                    j++;
                    monthsNeeded++;
                }
                //如果所需月数大于限定月数,则增加左边界
                if(monthsNeeded>m){
                    left = mid +1;
                    break;
                }
                //如果所需月数小于等于限定月数,则减小右边界
                if(monthsNeeded<=m) {
                    right = mid;
                }
            }

        }
        //输入最小人力
        System.out.println(left);
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值