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)
法二:别人的相同思路代码
思路:这个代码和上面的思路完全一致,只是最后求最小值的时候是用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]
法三:也可用带备忘录的回溯
参考: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/