饭馆菜品选择问题 | 青训营X豆包MarsCode 技术训练营

60 阅读4分钟

饭馆菜品选择问题解析

问题描述

小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 i 道菜是否含有蘑菇。

  1. 小C需要点 k 道菜。
  2. 在这 k 道菜中,最多有 m 道菜含有蘑菇。
  3. 我们需要尽可能使这些菜的总价格最低。
  4. 如果无法满足条件,则返回 -1

问题分析

我们可以将问题分解为以下步骤:

  • 分类菜品: 根据是否含有蘑菇,将菜品分为两组:不含蘑菇的菜和含有蘑菇的菜。

  • 排序菜品: 分别对这两组菜品按价格从低到高排序,以方便选择价格最低的组合。

  • 选择菜品:

    • 尝试选择不同数量的含蘑菇的菜,确保不超过 m 道。
    • 计算剩余需要选择的菜的数量(不含蘑菇的菜)。
    • 检查是否能满足总共 k 道菜的需求,如果可以,计算该组合的总价格。
  • 记录最小价格: 在所有可能的组合中,记录最小的总价格。

算法实现

def find_minimum_cost(s, a, m, k):
    # 将菜品分为含蘑菇和不含蘑菇两类
    mushroom_dishes = []
    non_mushroom_dishes = []

    for i in range(len(s)):
        if s[i] == '1':
            mushroom_dishes.append(a[i])
        else:
            non_mushroom_dishes.append(a[i])

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

    min_total_cost = float('inf')
    # 遍历所有可能的含蘑菇菜的数量
    for mushrooms in range(min(m, len(mushroom_dishes)) + 1):
        non_mushrooms = k - mushrooms
        if non_mushrooms <= len(non_mushroom_dishes):
            # 计算当前组合的总价格
            current_cost = sum(mushroom_dishes[:mushrooms]) + sum(non_mushroom_dishes[:non_mushrooms])
            # 更新最小总价格
            min_total_cost = min(min_total_cost, current_cost)

    # 返回结果
    return min_total_cost if min_total_cost != float('inf') else -1

# 测试用例
print(find_minimum_cost("001", [10, 20, 30], 1, 2))  # 输出: 30
print(find_minimum_cost("111", [10, 20, 30], 1, 2))  # 输出: -1
print(find_minimum_cost("0101", [5, 15, 10, 20], 2, 3))  # 输出: 30

代码解释

  1. 分类菜品:

    • 遍历菜品数组,使用两个列表 mushroom_dishes 和 non_mushroom_dishes 分别存储含和不含蘑菇的菜品价格。
  2. 排序菜品:

    • 对这两个列表分别进行排序,以便后续选择时总是优先选择价格最低的菜品。
  3. 选择菜品:

    • 遍历 mushrooms 从 0 到 min(m, len(mushroom_dishes)),这是可选择的含蘑菇菜的最大数量。
    • 计算 non_mushrooms 作为剩余需要选择的不含蘑菇的菜的数量。
    • 检查当前组合是否可以满足 k 道菜的需求。
    • 如果可以,计算当前组合的总价格,并与记录的最小价格进行比较,更新最小总价格。
  4. 返回结果:

    • 如果 min_total_cost 被更新过,返回最小总价格;否则返回 -1,表示无法满足条件。

复杂度分析

  • 时间复杂度: 主要受限于排序的时间复杂度 (O(n \log n)),其中 (n) 是菜品总数。
  • 空间复杂度: 使用了两个额外的列表存储菜品,空间复杂度为 (O(n))。

总结与感受

在这道题中,我们解决了一个关于如何在特定限制下优化选择的问题。小C需要从一组菜品中选择出价格最低的组合,同时满足特定的蘑菇菜品数量限制。这类问题通常涉及到分类、排序、组合选择等算法策略。

关键点总结
  1. 问题分解与分类:

    • 将问题分解为更小的可管理部分是解决复杂问题的有效方法。在这道题中,我们利用了菜品的特性(是否含有蘑菇)来进行分类,这使得后续的处理更加简单直接。
  2. 排序的优势:

    • 排序是一个非常强大的工具,通过排序,我们可以轻松地获取价格最低的组合。排序使得在选择菜品时,我们总是从价格最低的开始,确保尽可能降低总价。
  3. 遍历与组合:

    • 通过遍历可能的组合,我们能够系统地评估所有潜在的选择并选取最优方案。这种穷举法在可行的范围内是找到最优解的可靠方法。
  4. 边界条件的处理:

    • 处理好边界条件和特殊情况(如不能满足要求时返回 -1)是确保算法健壮性的重要部分。