题目:你需要制定一份 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/
来源:https://www.cnblogs.com/xxswkl/p/12380432.html
