我写的dp解法,先上代码:
def solution(m: int, n: int, p: list[list[int]]) -> int:
dp = [[math.inf for i in range(m+1)] for _ in range(m+1)]
#dp[i+1][j]是在第i天有j份食物的最小花费
dp[0][0] = 0
p.sort(reverse = False,key = lambda x:x[0])
lst_day = []
lst_cost = []
for i in p:
lst_day.append(i[0])
lst_cost.append(i[1])
temp_zhen = 0
for i in range(0,m):
if i in lst_day:
for j in range(m+1):
#i指下标,zhen也只能指代下标
zhen = i +1
temp = i
while zhen not in lst_day:
if zhen == m :
break
zhen += 1
distance = zhen - temp
if i == 0:
for z in range(max(distance-j,0),m-j+1):
dp[i+1][j + z] = min(dp[i][j] + z*(lst_cost[temp_zhen]),dp[i+1][j+z])
else:
for z in range(max(distance-j+1,0),m-j+1):
dp[i+1][j + z-1] = min(dp[i][j] + z*(lst_cost[temp_zhen]),dp[i+1][j-1+z])
temp_zhen += 1
else:
for j in range(m+1):
if j - 1 >=0:
dp[i+1][j-1] = dp[i][j]
return min(dp[-1])
if __name__ == "__main__":
# Add your test cases here
print(solution(5, 4, [[0, 2], [1, 3], [2, 1], [3, 2]]) == 7)
print(solution(4,3,[[0,3],[2,2],[3,1]]))
我的这段代码实现了一个动态规划算法,用于解决一种优化问题。具体来说,它的目的是在一个给定的资源分配场景中,计算最小的花费。可以从以下几个方面来分析代码的功能与实现过程。 函数签名与输入输出 def solution(m: int, n: int, p: list[list[int]]) -> int:
1.m 和 n 分别是问题的维度或规模,m 通常与物品的数量、资源的大小等有关,n 是任务数量或类似的集合大小。 2.p 是一个二维列表,包含了若干对数字,每一对 [day, cost] 表示某天 day 上的花费 cost。
动态规划数组的初始化 dp = [[math.inf for i in range(m+1)] for _ in range(m+1)] dp[0][0] = 0
3.dp[i][j] 代表在第 i 天结束时,拥有 j 份食物的最小花费。 4.初始化时,所有的花费都设置为无穷大 (math.inf),这是为了在后续的动态规划过程中能够正确地进行最小值计算。 5.dp[0][0] = 0 表示在开始时(第0天),没有花费,食物数为0。
对输入 p 的处理 p.sort(reverse=False, key=lambda x: x[0]) lst_day = [] lst_cost = [] for i in p: lst_day.append(i[0]) lst_cost.append(i[1])
6.对 p 列表按照 day 进行排序,使得可以按天依次处理各项任务。 7.lst_day 存储所有的天数,lst_cost 存储对应的花费。
动态规划的核心计算 temp_zhen = 0 for i in range(0, m): if i in lst_day: for j in range(m+1): zhen = i + 1 temp = i while zhen not in lst_day: if zhen == m: break zhen += 1 distance = zhen - temp if i == 0: for z in range(max(distance-j, 0), m-j+1): dp[i+1][j + z] = min(dp[i][j] + z*(lst_cost[temp_zhen]), dp[i+1][j+z]) else: for z in range(max(distance-j+1, 0), m-j+1): dp[i+1][j + z-1] = min(dp[i][j] + z*(lst_cost[temp_zhen]), dp[i+1][j-1+z]) temp_zhen += 1 else: for j in range(m+1): if j - 1 >= 0: dp[i+1][j-1] = dp[i][j]
8.外层循环 for i in range(0, m) 遍历每一天。 9.如果当天 (i day) 在 lst_day 中,则表示这天有相关任务,需要处理: 10.zhen 是一个指针,用于找到下一个与当前 i 相关的任务的天数。 11.distance 表示两个任务之间的天数差,接下来的循环根据这个差值来更新 dp 数组,计算在这段时间内所需的最小花费。 12.具体来说,内层循环根据当前的食物数量 j 和任务的天数差,计算在执行任务时的花费,并更新 dp 数组。使用 min() 来保证选择最优的花费方案。 13.如果当天不在 lst_day 中,则只是将前一天的花费转移到今天,不进行额外的花费增加。
结果返回 return min(dp[-1])
14.最后返回 dp 数组最后一行(即第 m 天的所有状态)中的最小值,这表示在第 m 天结束时,拥有任意食物数量的最小花费。
测试案例 print(solution(5, 4, [[0, 2], [1, 3], [2, 1], [3, 2]]) == 7) print(solution(4, 3, [[0, 3], [2, 2], [3, 1]]))
15.第一个测试案例中,传入的任务是 [[0, 2], [1, 3], [2, 1], [3, 2]],其中每个任务对应一个天数和花费。期望输出是 7,表示完成这些任务的最小花费。 16.第二个测试案例同样是一个资源分配问题,传入的任务是 [[0, 3], [2, 2], [3, 1]]。
总结 这段代码通过动态规划的思想解决了一个资源调度问题。在每一天,代码根据不同的任务安排以及前一天的状态来计算最小花费。通过合理的状态转移,最终得到在给定任务完成后的最小花费值。