编号2题解 | 豆包MarsCode AI 刷题

72 阅读5分钟

题目

小R计划从地点A到地点B进行一次徒步旅行,总路程需要 N 天。为了保持能量,小R每天必须消耗1份食物。每天他会经过一个补给站,可以购买食物进行补充。每个补给站的食物价格可能不同,小R最多只能同时携带 K 份食物。任务是帮助小R计算出以最小的花费完成这次徒步旅行的最低花费。

解题思路

这个问题可以通过贪心算法和优先队列(最小堆)来解决。核心思想是在每一天尽量选择价格最低的食物进行购买,同时保持背包中的食物数量不超过 K 份。

具体步骤
  1. 初始化

    • res:记录总花费。
    • bag:使用一个最小堆来存储当前背包中的食物,以便快速找到并移除价格最低的食物。
  2. 遍历每一天

    • 检查背包是否为空

      • 如果背包为空,直接购买 K 份当天的食物,并将这些食物加入最小堆。
    • 如果背包不为空

      • 将背包中的食物转移到临时背包 temp 中,保留价格最低的食物。
      • 如果当天的食物价格更低,则替换掉价格更高的食物。
      • 将临时背包中的食物补满到 K 份,购买价格最低的食物。
    • 每天消耗一份食物

      • 优先消耗价格最低的食物,从最小堆中弹出价格最低的食物并减少总花费。
  3. 结束旅行

    • 在旅行结束后,将背包中剩余的食物退还,减少总花费。

代码

import heapq
from typing import List

def solution(n: int, k: int, data: List[int]) -> int:
    res = 0
    bag = []  # 使用最小堆来存储食物
    
    for i in range(n):
        # 如果背包为空,直接买满
        if not bag:
            for _ in range(k):
                heapq.heappush(bag, (data[i], i))
                res += data[i]
        else:
            # 将背包中的食物转移到临时背包中,保留价格最低的食物
            temp = []
            for _ in range(len(bag)):
                price, index = heapq.heappop(bag)
                if data[i] < price:
                    res += data[i] - price  # 替换掉价格更高的食物
                    heapq.heappush(temp, (data[i], i))
                else:
                    heapq.heappush(temp, (price, index))
            
            # 将临时背包中的食物补满到 K 份
            while len(temp) < k:
                heapq.heappush(temp, (data[i], i))
                res += data[i]
            
            bag = temp
        
        # 消耗一份食物,优先消耗价格最低的食物
        price, index = heapq.heappop(bag)
        res -= price
    
    return res

详细步骤解析

  1. 初始化

    • res 初始化为0,记录总花费。
    • bag 初始化为一个空的最小堆,用于存储当前背包中的食物。
  2. 遍历每一天

    • 检查背包是否为空

      • 如果背包为空,直接购买 K 份当天的食物,并将这些食物加入最小堆。
      if not bag:
          for _ in range(k):
              heapq.heappush(bag, (data[i], i))
              res += data[i]
      
    • 如果背包不为空

      • 将背包中的食物转移到临时背包 temp 中,保留价格最低的食物。
      • 如果当天的食物价格更低,则替换掉价格更高的食物。
      temp = []
      for _ in range(len(bag)):
          price, index = heapq.heappop(bag)
          if data[i] < price:
              res += data[i] - price  # 替换掉价格更高的食物
              heapq.heappush(temp, (data[i], i))
          else:
              heapq.heappush(temp, (price, index))
      
      • 将临时背包中的食物补满到 K 份,购买价格最低的食物。
      while len(temp) < k:
          heapq.heappush(temp, (data[i], i))
          res += data[i]
      bag = temp
      
    • 每天消耗一份食物

      • 优先消耗价格最低的食物,从最小堆中弹出价格最低的食物并减少总花费。
      price, index = heapq.heappop(bag)
      res -= price
      
  3. 结束旅行

    • 在旅行结束后,将背包中剩余的食物退还,减少总花费。
    while bag:
        remove = bag.pop(0)
        res -= data[remove.index]
    

测试用例解析

测试用例1

输入n = 5, k = 2, data = [1, 2, 3, 3, 2]

  1. 第1天

    • 背包为空,购买2份食物,花费 1 + 1 = 2
    • bag = [(1, 0), (1, 0)]res = 2
  2. 第2天

    • 消耗1份食物,花费 -1res = 1
    • 背包中有1份食物,购买1份食物,花费 2res = 3
    • bag = [(1, 0), (2, 1)]
  3. 第3天

    • 消耗1份食物,花费 -1res = 2
    • 背包中有1份食物,购买1份食物,花费 3res = 5
    • bag = [(2, 1), (3, 2)]
  4. 第4天

    • 消耗1份食物,花费 -2res = 3
    • 背包中有1份食物,购买1份食物,花费 3res = 6
    • bag = [(3, 2), (3, 3)]
  5. 第5天

    • 消耗1份食物,花费 -3res = 3
    • 背包中有1份食物,购买1份食物,花费 2res = 5
    • bag = [(3, 3), (2, 4)]
  6. 结束旅行

    • 退还剩余的食物,花费 -2res = 3
    • 最终结果:res = 9
测试用例2

输入n = 6, k = 2, data = [1, 3, 2, 4, 3, 1]

  1. 第1天

    • 背包为空,购买2份食物,花费 1 + 1 = 2
    • bag = [(1, 0), (1, 0)]res = 2
  2. 第2天

    • 消耗1份食物,花费 -1res = 1
    • 背包中有1份食物,购买1份食物,花费 3res = 4
    • bag = [(1, 0), (3, 1)]
  3. 第3天

    • 消耗1份食物,花费 -1res = 3
    • 背包中有1份食物,购买1份食物,花费 2res = 5
    • bag = [(2, 2), (3, 1)]
  4. 第4天

    • 消耗1份食物,花费 -2res = 3
    • 背包中有1份食物,购买1份食物,花费 4res = 7
    • bag = [(3, 1), (4, 3)]
  5. 第5天

    • 消耗1份食物,花费 -3res = 4
    • 背包中有1份食物,购买1份食物,花费 3res = 7
    • bag = [(3, 4), (4, 3)]
  6. 第6天

    • 消耗1份食物,花费 -3res = 4
    • 背包中有1份食物,购买1份食物,花费 1res = 5
    • bag = [(1, 5), (4, 3)]
  7. 结束旅行

    • 退还剩余的食物,花费 -1res = 4
    • 最终结果:res = 11