饭馆菜品选择问题 题解 | 豆包MarsCode AI 刷题

39 阅读4分钟

问题描述

小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a[i]。其中一些菜含有蘑菇,s[i] 代表第 i 道菜是否含有蘑菇。如果 s[i] = '1',表示该菜含有蘑菇,否则没有。

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

解题思路

这个问题可以通过贪心算法和分类处理来解决。我们可以将菜品分为两类:含蘑菇的菜和不含蘑菇的菜。然后通过对这两类菜品的价格进行排序,尽量选择价格最小的菜品,满足小C的要求。

思路解析:

  1. 菜品分类:

    • 通过 s[i] 判断菜品是否含有蘑菇,分别将含有蘑菇的菜品和不含蘑菇的菜品分开。
  2. 排序:

    • 对含蘑菇的菜品和不含蘑菇的菜品分别按价格从小到大排序,确保我们每次选择最便宜的菜品。
  3. 菜品选择:

    • 我们需要选择 k 道菜,并且最多选择 m 道含有蘑菇的菜。因此,选择含蘑菇的菜品的数量应该在 0 到 m 之间。
    • 对于每一种可能的选择含蘑菇的菜品的数量,计算总价格,选出最小的价格。
  4. 验证是否可行:

    • 检查在某一选择下,是否能够选择足够数量的菜品。如果无法满足条件,则输出 -1

代码实现

def solution(s: str, a: list, m: int, k: int) -> int:
    # 划分菜品为含蘑菇和不含蘑菇的菜
    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_cost = float('inf')
    for x in range(0, min(m, k) + 1):  # x 表示选择蘑菇菜品的数量
        y = k - x  # y 表示选择不含蘑菇菜品的数量
        
        # 如果选择的菜品数量超过了可选的数量,跳过
        if x > len(mushroom_dishes) or y > len(non_mushroom_dishes):
            continue
        
        # 计算当前选择方案的总价格
        cost = sum(mushroom_dishes[:x]) + sum(non_mushroom_dishes[:y])
        min_cost = min(min_cost, cost)
    
    # 如果没有有效方案,返回 -1
    return min_cost if min_cost != float('inf') else -1

代码解释

  1. 数据分类:

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

    • 对 mushroom_dishes 和 non_mushroom_dishes 分别进行升序排序,确保我们可以选择价格最小的菜品。
  3. 枚举蘑菇菜品数量:

    • 使用变量 x 表示选择的蘑菇菜品数量,枚举的范围是 0 到 min(m, k),即最多选择 m 道蘑菇菜品,且总共需要选择 k 道菜品。
    • 对于每一个选择蘑菇菜品的数量 x,计算需要选择不含蘑菇的菜品数量 y = k - x
  4. 判断是否可行:

    • 如果选择的蘑菇菜品数量 x 超过了实际可选的数量,或者选择的非蘑菇菜品数量 y 超过了实际可选的数量,则跳过该情况。
  5. 计算总价格:

    • 对于每一种可行的选择,计算总价格,并更新最小总价格。
  6. 返回结果:

    • 如果找到可行的方案,返回最小总价格;否则返回 -1

复杂度分析

  • 时间复杂度:

    • 将菜品分为两类需要 O(n) 的时间。
    • 对这两类菜品进行排序分别需要 O(n log n) 的时间。
    • 枚举蘑菇菜品数量需要 O(min(m, k)),每次枚举时的计算为常数时间。
    • 综合时间复杂度为 O(n log n)
  • 空间复杂度:

    • 使用了两个列表来存储菜品信息,空间复杂度为 O(n)

测试用例

测试用例 1

输入:

s = "001"
a = [10, 20, 30]
m = 1
k = 2

输出:

30

解释:有 3 道菜,正反面数字分别为 (10, 20)(20, 30)(30, 10)。选择 2 道菜,且最多选择 1 道蘑菇菜品,最小的总价格是 30。

测试用例 2

输入:

s = "111"
a = [10, 20, 30]
m = 1
k = 2

输出:

-1

解释:有 3 道菜,且每道菜都含有蘑菇,但只能选择最多 1 道蘑菇菜品,因此无法选择符合条件的菜品。

测试用例 3

输入:

s = "0101"
a = [5, 15, 10, 20]
m = 2
k = 3

输出:

30

解释:有 4 道菜,选择 3 道菜,且最多选择 2 道蘑菇菜品,最小的总价格是 30。

总结

这道题目考察了如何将问题分解为子问题,并利用排序和枚举来优化解法。通过合理分类和选择,我们可以快速找到最优解