补给站最优花费问题| 豆包MarsCode AI刷题

54 阅读4分钟

我写的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]]。

总结 这段代码通过动态规划的思想解决了一个资源调度问题。在每一天,代码根据不同的任务安排以及前一天的状态来计算最小花费。通过合理的状态转移,最终得到在给定任务完成后的最小花费值。