【每日一题Day208】LC1335工作计划的最低难度 | 动态规划

工作计划的最低难度【LC1335】

你需要制定一份 d 天的工作计划表。工作之间存在依赖,要想执行第 i 项工作,你必须完成全部 j 项工作( 0 <= j < i)。

你每天 至少 需要完成一项任务。工作计划的总难度是这 d 天每一天的难度之和,而一天的工作难度是当天应该完成工作的最大难度。

给你一个整数数组 jobDifficulty 和一个整数 d,分别代表工作难度和需要计划的天数。第 i 项工作的难度是 jobDifficulty[i]

返回整个工作计划的 最小难度 。如果无法制定工作计划,则返回 -1

我和动态规划的关系就像是见过但是总是隐隐约约想不起来的陌生人
类似题目

dfs+记忆化
  • 思路

    题意可以转化为分割成d个子数组,使d个子数组的最大值之和最小。

    • 寻找子问题:如果将后 [ k , n − 1 ] [k,n-1] [k,n1]个任务在一天内完成,那么前面 [ 0 , k − 1 ] [0,k-1] [0,k1]个任务需要在 d − 1 d-1 d1天完成,因此找到了子问题,可以通过递归/动态规划来解决。(dfs+记忆化的形式最好理解)

    • 定义dfs函数:定义 d f s ( i , j ) dfs(i,j) dfs(i,j)为在 i i i天完成 [ 0 , j ] [0,j] [0,j]个任务所需要的最小难度

    • 递归入口:那么 d f s ( n − 1 , d ) dfs(n-1,d) dfs(n1,d)即为答案

    • 递归逻辑

      由于每一天都需要有工作任务,那么在决定第 i i i天的工作任务时,必须预留 i − 1 i-1 i1个工作。因此在安排第 i i i天的工作任务时,我们枚举 [ i − 1 , j ] [i-1,j] [i1,j]个任务,分割子数组,记录子数组中的最大值(当天的工作难度),然后递归到下一天,取最小值返回。
      d f s ( i , j ) = m i n k = i − 1 j { d f s ( i − 1 , k − 1 ) + m a x p = k j ( j o b D i f f i c u l t y [ p ] ) } dfs(i,j)= min_{k= i-1}^{j}\{dfs(i-1,k-1)+max_{p=k}^{j}(jobDifficulty[p])\} dfs(i,j)=mink=i1j{dfs(i1,k1)+maxp=kj(jobDifficulty[p])}

    • 递归边界

      只有一天时,必须完成所有任务

  • 实现

    (i可以整体缩小1)

    class Solution {
        int[] jobDifficulty;
        int[][] memo;
        int res = Integer.MAX_VALUE;
        public int minDifficulty(int[] jobDifficulty, int d) {
            this.jobDifficulty = jobDifficulty;
            // 分割成d个子数组,使d个子数组的最大值之和最小
            // dfs(i,j) j天完成[0,i]项工作所需要的最小难度
            int n = jobDifficulty.length;
            if (n < d){
                return -1;
            }
            memo = new int[d + 1][n];
            for (int i = 0; i <= d; i++){
                Arrays.fill(memo[i], -1);
            }
            return dfs(d, n - 1);
            
        }
        public int dfs(int i, int j){
            // if (i < 0 || j <= 0) return 0;
            if (memo[i][j] != -1) return memo[i][j];
            // 只有一天
            if (i == 1){
                int mx = 0;
                for (int k = 0; k <= j; k++){
                    mx = Math.max(mx, jobDifficulty[k]);
                }
                memo[i][j] = mx;
                return mx;
            }
            int res = Integer.MAX_VALUE;
            int mx = -1;
            // 枚举子数组范围 [i - 1, j] 留下i - 1个元素
            for (int k = j; k >= i - 1; k--){
                mx = Math.max(mx, jobDifficulty[k]);
                res = Math.min(res, mx + dfs(i - 1,k - 1));
            }
            memo[i][j] = res;
            return res;
        }
    }
    
    • 复杂度

      • 时间复杂度: O ( n 2 d ) O(n^2d) O(n2d)
      • 空间复杂度: O ( n d ) O(nd) O(nd)
递推
  • 实现

    class Solution {
        public int minDifficulty(int[] a, int d) {
            int n = a.length;
            if (n < d) return -1;
    
            var f = new int[d][n];
            f[0][0] = a[0];
            for (int i = 1; i < n; i++)
                f[0][i] = Math.max(f[0][i - 1], a[i]);
            for (int i = 1; i < d; i++) {
                for (int j = n - 1; j >= i; j--) {
                    f[i][j] = Integer.MAX_VALUE;
                    int mx = 0;
                    for (int k = j; k >= i; k--) {
                        mx = Math.max(mx, a[k]); // 从 a[k] 到 a[j] 的最大值
                        f[i][j] = Math.min(f[i][j], f[i - 1][k - 1] + mx);
                    }
                }
            }
            return f[d - 1][n - 1];
        }
    }
    
    作者:灵茶山艾府
    链接:https://leetcode.cn/problems/minimum-difficulty-of-a-job-schedule/solutions/2271631/jiao-ni-yi-bu-bu-si-kao-dong-tai-gui-hua-68nx/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    
    • 复杂度

      • 时间复杂度: O ( n 2 d ) O(n^2d) O(n2d)
      • 空间复杂度: O ( n d ) O(nd) O(nd)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
庐阳区2022年信息学竞赛试题工作日(day)将是一项具有挑战性和丰富内容的学术竞赛活动。信息学竞赛是一项旨在考察参赛者在计算机科学、算法设计和编程技能等方面的能力的竞赛活动。 在庐阳区2022年信息学竞赛试题中,参赛者将面临各种具有难度的问题,这些问题往往涉及到计算机科学的基本概念和算法设计。参赛者需要独立思考和解决这些问题,表现出对编程语言和算法的掌握能力。 试题中可能包括编写程序解决问题的任务,参赛者需要用合适的编程语言编写程序,并根据题目需求输出正确的结果。这个过程要求参赛者在理解问题、设计算法和实现代码等方面具备扎实的计算机科学基础知识和编程技巧。 庐阳区2022年信息学竞赛试题将在工作日进行。参赛者需要在规定的时间内完成试题,并提交自己的答案。竞赛的评判标准将根据参赛者题目的正确性、程序的效率和代码的质量等方面进行评估。 信息学竞赛的目的是激发学生对计算机科学的兴趣,提高他们的编程和问题解决能力。通过参与竞赛,学生们可以拓宽视野、增加知识储备,并提高自己在计算机科学领域的竞争力。 参与庐阳区2022年信息学竞赛试题的选手们将面临一项充满挑战的学术竞赛,他们需要发挥自己的聪明才智,展现自己的实力。希望这次竞赛能够激发更多对信息学的热爱,培养更多的优秀人才。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值