题目解析:36.饭店菜品选择问题 | 豆包MarsCode AI刷题

59 阅读3分钟

问题描述

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

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


测试样例

样例1:

输入:s = "001", a = [10, 20, 30], m = 1, k = 2
输出:30

样例2:

输入:s = "111", a = [10, 20, 30], m = 1, k = 2
输出:-1

样例3:

输入:s = "0101", a = [5, 15, 10, 20], m = 2, k = 3
输出:30

分析这道题的关键点可以帮助我们更好地理解问题的核心,并确保解决方案的正确性和效率。以下是这道题的关键点:

1. 问题定义

  • 目标: 小C希望点 k 道菜,且总价格尽可能低。

  • 限制条件:

    • 最多只能选择 m 道含有蘑菇的菜。
    • 如果无法满足上述条件,则输出 -1

2. 输入数据

  • s: 字符串,长度为 n,表示每道菜是否含有蘑菇('1' 表示含有,'0' 表示不含)。
  • a: 列表,长度为 n,表示每道菜的价格。
  • m: 整数,表示最多可以选择多少道含有蘑菇的菜。
  • k: 整数,表示需要选择的菜品总数。

3. 关键步骤

a. 分类菜品

  • 根据是否有蘑菇将菜品分为两组:

    • with_mushroom: 含有蘑菇的菜品的价格列表。
    • without_mushroom: 不含蘑菇的菜品的价格列表。

b. 排序

  • 对这两组菜品的价格进行排序,以便后续计算最小成本时能够快速找到最优组合。

c. 前缀和计算

  • 使用 itertools.accumulate 计算每个数组的前缀和,这样可以快速查找任意数量的菜品组合的成本。

    • prefix_sum_without: 存储 without_mushroom 的前缀和。
    • prefix_sum_with: 存储 with_mushroom 的前缀和。

d. 寻找最小成本

  • 遍历可能的选择方案,即选择不同数量的含有蘑菇的菜品(从0到m),并相应地选择不含蘑菇的菜品以达到总共k道菜品的要求。
  • x 是选择的含有蘑菇的菜品的数量。
  • y 是选择的不含蘑菇的菜品的数量,由 y = k - x 得出。
  • 如果 y 在有效范围内(即 y >= 0 且 y <= len(without_mushroom)),则计算当前组合的成本,并更新最小成本。

e. 返回结果

  • 最后,如果找到了有效的组合,则返回最小成本;否则返回 -1 表示无法满足条件。
from itertools import accumulate
def solution(s, a, m, k):
    n = len(s)
    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()
    
    # 计算前缀和以便快速查找
    prefix_sum_without = [0] + list(accumulate(without_mushroom))
    prefix_sum_with = [0] + list(accumulate(with_mushroom))
    
    # 寻找最小成本
    min_cost = float('inf')
    for x in range(min(m + 1, len(with_mushroom) + 1)):  # x 是有蘑菇的菜的数量
        y = k - x  # y 是没有蘑菇的菜的数量
        if y >= 0 and y <= len(without_mushroom):
            cost = prefix_sum_with[x] + prefix_sum_without[y]
            min_cost = min(min_cost, cost)
    
    return min_cost if min_cost != float('inf') else -1