华为OD题目: 核酸检测人员安排

核酸检测人员安排

参考 https://blog.csdn.net/qq_34465338/article/details/128648074
时间限制: 1s 空间限制: 256MB 限定语言: 不限
题目描述:
在系统、网络均正常的情况下组织核酸 采样员和志愿者对人群进行核酸检测筛查。每名采样员的效率不同,采样效率为N人/小时。
由于外界变化,采样员的效率会以M人/小时为粒度发生变化,M为采样效率浮动粒度,M=N10%,输入保证N10%的结果为整数。
采样员效率浮动规则: 采样员需要一名志愿者协助组织才能发挥正常效率,在此基础上,每增加一名志愿者,效率提升1M,最多提升3M;如果没有志愿者协助组织,效率下降2M。
怎么安排速度最快? 求总最快检测效率(总检查效率为各采样人员效率值相加)。

输入描述:
第一行: 第一个值,采样员人数,取值范围[1,100]: 第二个值,志愿者人数,取值范围[1,500];第二行: 各采样员基准效率值(单位人/小时),取值范围[60,600],保证序列中每项值计算10%为整数
输出描述:
第一行: 总最快检测效率(单位人/小时)
补充说明:
输入需要保证采样员基准效率值序列的每个值*10%为整数

示例1
输入:
2 2
200 200
输出:
400

解题思路:

  • 可以使用动态规划,只是比较的时候比较复杂
  • dp[i][j] 表示: 从0到i个核酸采集员,总计i个采集员,j个志愿者的最大效率
  • 那么动态方程就是,比较 刚好到第i个采集员的时候, 有j个志愿者,分以下几种情况,
  • 0个志愿者给 第i个采集员 dp[i][j] = dp[i-1][j] + e -0.2e
  • 1个志愿者给 第i个采集员 dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + curEff);
  • 2个志愿者给 第i个采集员 dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 2] + curEff + M);
  • 3个志愿者给 第i个采集员 dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 3] + curEff + 2 * M);
  • 4个志愿者给 第i个采集员 dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 3] + curEff + 3 * M);
  • 超过4个的话,就没有意义了,反而多占用志愿者数量,因此不比较
  • 取上面几种情况里最大的一个
  • 如果志愿者>=1, 比较1个志愿者是给第i个采样员的累计效率, 与1个志愿者不给第i个采样员的累积效率
  • dp[i][j] = max(dp[i-1][j] + e -0.2e, dp[i-1][j-1] + e);
  • 如果志愿者>=2, 则 比较完上面的后,继续比较 (2个志愿者,提升1M)
  • dp[i][j] = max(dp[i][j], dp[i-1][j-2] + e + 0.1e * (2-1));
  • 如果志愿者>=3, 则 比较完上面的后,继续比较 (3个志愿者,提升2M)
  • dp[i][j] = max(dp[i][j], dp[i-1][j-3] + e + 0.1e * (3-1));
  • 如果志愿者>=4, 则 比较完上面的后,继续比较 (4个志愿者,提升2M)
  • dp[i][j] = max(dp[i][j], dp[i-1][j-4] + e + 0.1e * (4-1));
import java.util.*;

public class My {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        String[] strings = str.split(" ");
        //采集人员人数
        int nurseNum = Integer.parseInt(strings[0]);
        //志愿者人数
        int volunteerNum = Integer.parseInt(strings[1]);

        String line = sc.nextLine();
        String[] effStrArr = line.split(" ");
        //每个采集员的效率
        int[] eff = new int[nurseNum + 1];
        for (int i = 0; i < nurseNum; i++) {
            eff[i] = Integer.parseInt(effStrArr[i]);
        }
        //动态规划的方程
        int[][] dp = new int[nurseNum + 1][volunteerNum + 1];


        for (int i = 1; i <= nurseNum; i++) {
            for (int j = 0; j <= volunteerNum; j++) {
                //当前人员(第i个采集人员)的效率,因为eff是从0开始,所以要减1
                int curEff = eff[i - 1];
                int M = (int) (0.1 * curEff);
                //最开始, dp[i][j] 取值为 当前采集员(第i个采集员),没有志愿者协助
                dp[i][j] = dp[i - 1][j] + curEff - 2 * M;
                if (j >= 1) {
                    //有 1 个志愿者协助当前采集员
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + curEff);
                }
                if (j >= 2) {
                    //有 2 个志愿者协助当前采集员
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 2] + curEff + M);
                }
                if (j >= 3) {
                    //有 3 个志愿者协助当前采集员
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 3] + curEff + 2 * M);
                }
                if (j >= 4) {
                    //有 4 个志愿者协助当前采集员
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 3] + curEff + 3 * M);
                }

            }
        }

//        for (int i = 0; i <= nurseNum; i++) {
//            for (int j = 0; j <= volunteerNum; j++) {
//                System.out.print(dp[i][j] + "\t");
//            }
//            System.out.println();
//        }

        System.out.println(dp[nurseNum][volunteerNum]);

    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值