1335工作计划的最低难度

题目:你需要制定一份 d 天的工作计划表。工作之间存在依赖,要想执行第 i 项工作,你必须完成全部 j 项工作( 0 <= j < i)。你每天 至少 需要完成一项任务。工作计划的总难度是这 d 天每一天的难度之和,而一天的工作难度是当天应该完成工作的最大难度。给你一个整数数组 jobDifficulty 和一个整数 d,分别代表工作难度和需要计划的天数。第 i 项工作的难度是 jobDifficulty[i]。返回整个工作计划的 最小难度 。如果无法制定工作计划,则返回 -1

 

法一:自己的代码

思路:典型的二维动态规划题目,动态规划的两个关键地方,一是动态转移方程,二是初始条件,这个题中的初始条件可以单独计算第一列,也可以添加一列全0列,直接处理,

from typing import List
class Solution:
    def minDifficulty(self, jobDifficulty: List[int], d: int) -> int:
        size = len(jobDifficulty)
        dp = [[0] * d for i in range(size)]
        # 初始化,为了节省求最大值的时间
        dp[0][0] = jobDifficulty[0]
        for i in range(1,size):
            dp[i][0] = max(jobDifficulty[i], dp[i-1][0])
        # dp[row][col]表示第row+1个工作用col+1天的最小值
        for col in range(1, d):
            for row in range(col, size):
                a,b = 0, float('inf')
                # 这里倒序计算最大值更省时,
                for i in range(row-1, col-2, -1):
                    a = max(a, jobDifficulty[i+1])
                    b = min(dp[i][col-1] + a, b)
                dp[row][col] = b
                ## 优化前的代码
                # 一定要注意这里range(col-1,row),要从col-1开始,因为从0到col-1(包含col-1)有col个工作,恰好够col天分,一天一个,
                # 因为dp[row][col]表示的是用col+1天分配row+1个工作,
                # 这里dp[i][col-1]中i的初始值必须要和col-1相等,表示col-1天至少要有col-1个工作,
                # dp[row][col] = min(dp[i][col-1]+max(jobDifficulty[i+1:row+1]) for i in range(col-1,row))
        return dp[-1][-1]
if  __name__ == '__main__':
    solution = Solution()
    result = solution.minDifficulty(jobDifficulty = [7,1,7,1,7,1], d = 3)
    print(result)
View Code

法二:别人的相同思路代码

思路:这个代码和上面的思路完全一致,只是最后求最小值的时候是用if dp[i - 1][k] + work < dp[i][j]: 的,由于是求两个数的最小值没有用min,节省了很多时间,这个技巧应该学习,

from typing import List
class Solution:
    def minDifficulty(self, jobDifficulty: List[int], d: int) -> int:
        jc = len(jobDifficulty)
        if d > jc: return -1
        # 注意这里定义dp的时候行列都加了1,第一行和第一列都没有用
        dp = [[-1 for i in range(jc + 1)] for i in range(d + 1)]
        # 初始化第一列
        dp[1][1] = jobDifficulty[0]
        for i in range(2, jc + 1):
            dp[1][i] = max(dp[1][i - 1], jobDifficulty[i - 1])
        for i in range(2, d + 1):
            for j in range(i, jc + 1):
                dp[i][j] = dp[i - 1][j - 1] + jobDifficulty[j - 1]
                work = jobDifficulty[j - 1]
                # 仍然是倒序遍历
                for k in range(j - 2, i - 2, -1):
                    work = max(jobDifficulty[k], work)
                    # 如果它更小,则用更小的值替代
                    if dp[i - 1][k] + work < dp[i][j]:
                        dp[i][j] = dp[i - 1][k] + work
        return dp[d][jc]
View Code

法三:也可用带备忘录的回溯

参考:https://leetcode-cn.com/problems/minimum-difficulty-of-a-job-schedule/solution/python-3-jian-dan-shi-xian-hui-su-suan-fa-ji-yi-hu/

posted on 2020-02-28 21:43  吃我一枪  阅读(274)  评论(0编辑  收藏  举报

导航