LeetCode 1723 完成所有工作的最短时间 题解

LeetCode 1723 完成所有工作的最短时间 题解

给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间。
请你将这些工作分配给 k 位工人。所有工作都应该分配给工人,且每项工作只能分配给一位工人。工人的 工作时间 是完成分配给他们的所有工作花费时间的总和。请你设计一套最佳的工作分配方案,使工人的 最大工作时间 得以 最小化 。
返回分配方案中尽可能 最小 的 最大工作时间 。
示例 1:
输入:jobs = [3,2,3], k = 3
输出:3
解释:给每位工人分配一项工作,最大工作时间是 3 。
示例 2:
输入:jobs = [1,2,4,7,8], k = 2
输出:11
解释:按下述方式分配工作:
1 号工人:128(工作时间 = 1 + 2 + 8 = 112 号工人:47(工作时间 = 4 + 7 = 11)
最大工作时间是 11 。 
提示:
1 <= k <= jobs.length <= 12
1 <= jobs[i] <= 10^7

参考

在这里插入图片描述

class Solution {
    //https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/solution/gong-shui-san-xie-yi-ti-shuang-jie-jian-4epdd/
    int[] jobs;
    int n, k;
    int ans = 0x3f3f3f3f;
    public int minimumTimeRequired(int[] _jobs, int _k) {
        jobs = _jobs;
        n = jobs.length;
        k = _k;
        int[] sum = new int[k];
        dfs(0, 0, sum, 0);
        return ans;
    }
    /**
     * u     : 当前处理到那个 job
     * used  : 当前分配给了多少个工人了
     * sum   : 工人的分配情况          例如:sum[0] = x 代表 0 号工人工作量为 x
     * max   : 当前的「最大工作时间」
     */
    void dfs(int u, int used, int[] sum, int max) {
        if (max >= ans) return;//一旦发现某次遍历时最大时间超过了ans就不用往下走了,直接剪枝
        if (u == n) {
            ans = max;
            return;
        }
        // 优先分配给「空闲工人」,这样的话,第一轮下来,走到第n个job的时候,max等于先让每个人都有工作,然后剩下的都扔给第一个工人所需要的工作时间
        if (used < k) {
            sum[used] = jobs[u];//要保证这里的sum[used]为0,也就是不能在底下的for里对这一位赋值,也就是i必须小于used而不是k
            dfs(u + 1, used + 1, sum, Math.max(sum[used], max));
            sum[used] = 0;
        }
        //for循环的条件里不能是i<k
        for (int i = 0; i < used; i++) {//前期一直深入,used=k,平均分配,每个人都有工作;后期回退的时候,used<k,由于前面有一句sum[used] = 0,所以是有k-used个工人是空闲的,也就是不平均分配
            sum[i] += jobs[u];
            dfs(u + 1, used, sum, Math.max(sum[i], max));
            sum[i] -= jobs[u];
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值