第36题|豆包MarsCode AI刷题

13 阅读2分钟

问题描述

小C来到了一家饭馆,这里共有 nn 道菜,第 ii 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 ii 道菜是否含有蘑菇。如果 s_i = '1',那么第 ii 道菜含有蘑菇,否则没有。

小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1

问题思路分析

这是一个组合优化问题,目标是从两类菜品中选择 k 道菜,使得总价格最低,并满足限制条件:至多选 m 道含蘑菇的菜。

关键点:

  1. 分组处理:

    • 将菜品分为含蘑菇和不含蘑菇两类,便于分别排序和选择。
  2. 枚举选择:

    • 枚举选择的含蘑菇菜品数量 x,剩余的 k−x 道菜必须从不含蘑菇菜品中选择。
  3. 排序贪心:

    • 为了使总价格最低,优先选择价格最低的菜品(按价格排序后取前若干个)。
  4. 可行性检查:

    • 确保所需的菜品数量 x 和 y=k−x 都能够从对应的菜品中取出。

算法步骤

  1. 将菜品分为两组:

    • 含蘑菇的菜品:with_mushroom
    • 不含蘑菇的菜品:without_mushroom
  2. 对两组分别按价格升序排序。

  3. 枚举含蘑菇的菜品数量 xx:

    • 对于每个 xx,计算不含蘑菇的菜品数量 y=k−xy=k−x。
    • 如果 x \leq \text{len(with_mushroom)} 且 y \leq \text{len(without_mushroom)},则计算总价格。
  4. 记录所有满足条件的方案中的最小价格。

  5. 如果无法找到任何满足条件的方案,返回 -1。

def solution(s: str, a: list, m: int, k: int) -> int:

    n = len(a)


# 将菜品分为含蘑菇和不含蘑菇两类
with_mushroom = []
without_mushroom = []

for i in range(n):
    if s[i] == '1':
        with_mushroom.append(a[i])
    else:
        without_mushroom.append(a[i])

# 分别对两类菜品按价格排序
with_mushroom.sort()
without_mushroom.sort()

# 初始化结果
min_price = float('inf')
possible = False

# 枚举含蘑菇的菜品数量 x
for x in range(min(m, k) + 1):  # x最多为m,且x不能超过k
    y = k - x  # 不含蘑菇的菜品数量
    
    # 检查是否能挑选到足够的菜品
    if x <= len(with_mushroom) and y <= len(without_mushroom):
        # 计算当前组合的总价格
        price = sum(with_mushroom[:x]) + sum(without_mushroom[:y])
        min_price = min(min_price, price)
        possible = True

# 如果找到了满足条件的方案,返回最小价格;否则返回-1
return min_price if possible else -1