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

114 阅读4分钟

饭馆菜品选择问题

问题描述

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

小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小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

代码示例

import itertools

def solution(s: str, a: list, m: int, k: int) -> int:
    n = len(s)
    if k > n or m < 0:
        return -1
    min_price = float('inf')
    for combination in itertools.combinations(range(n), k):
        price_sum = sum([a[i] for i in combination])
        mushroom_count = sum([1 for i in combination if s[i] == '1'])
        if mushroom_count <= m:
            min_price = min(min_price, price_sum)
    return min_price if min_price!= float('inf') else -1


if __name__ == '__main__':
    print(solution("001", [10, 20, 30], 1, 2) == 30)
    print(solution("111", [10, 20, 30], 1, 2) == -1)
    print(solution("0101", [5, 15, 10, 20], 2, 3) == 30)

问题理解

小C希望在一家饭馆点 k 道菜,且希望总价格尽可能低。同时,她希望所点的菜中最多只有 m 道菜含有蘑菇。我们需要找到满足这些条件的最小总价格,如果无法满足条件则返回 -1

算法步骤

  1. 边界条件检查

    • 如果 k 大于菜的总数 n,或者 m 小于 0,直接返回 -1
  2. 生成所有可能的组合

    • 使用组合生成算法(如递归或迭代)生成所有可能的 k 道菜的组合。
  3. 计算每个组合的总价格和蘑菇数量

    • 对于每个组合,计算总价格和蘑菇数量。
    • 如果蘑菇数量不超过 m,则更新最小总价格。
  4. 返回结果

    • 如果找到了满足条件的组合,返回最小总价格;否则返回 -1

具体步骤

  1. 初始化最小总价格为无穷大

  2. 生成所有可能的 k 道菜的组合

    • 使用递归或迭代生成所有可能的组合。
  3. 对于每个组合

    • 计算总价格。
    • 计算蘑菇数量。
    • 如果蘑菇数量不超过 m,则更新最小总价格。
  4. 返回最小总价格,如果没有满足条件的组合则返回 -1

代码分析

  • solution函数

    • 参数含义

      • s:一个字符串,其每个字符(这里主要涉及'0''1')用于标记对应位置元素的某种属性(例如是否为蘑菇等情况)。
      • a:一个整数列表,列表中的每个元素表示对应位置元素的价格,与字符串s的位置是一一对应的关系。
      • m:一个整数,表示在选取的元素组合中,字符串s里字符为'1'的元素个数的上限,即限制条件。
      • k:一个整数,表示要从字符串s(以及对应的整数列表a)中选取的元素个数。
    • 主要逻辑及步骤

      • 首先通过len(s)获取字符串s的长度n,并将最小价格min_price初始化为正无穷大(float('inf')),这样后续找到的任何有限价格都能更新它。

      • 然后使用itertools.combinations函数来生成从range(n)(即从0n - 1的整数序列,代表字符串s和列表a的索引)中选取k个元素的所有组合情况。对于每一种组合combination

        • 通过列表推导式[a[i] for i in combination]计算该组合在列表a中对应元素的价格总和price_sum,也就是将组合中每个索引对应的价格相加。
        • 同样通过列表推导式[1 for i in combination if s[i] == '1']统计该组合中字符串s里字符为'1'的元素个数mushroom_count,这里列表推导式生成的列表每个元素都是1,最后通过sum函数求和得到个数。
        • 判断mushroom_count是否小于等于m,如果是,则说明该组合满足条件,使用min函数更新min_price,取当前min_priceprice_sum中的较小值作为新的min_price
      • 最后,判断min_price是否还是正无穷大,如果是则表示没有找到满足条件的组合,返回-1;否则返回计算得到的最小价格min_price

这道题考察了组合生成、条件筛选和最小值查找等基本算法思想。通过这道题,可以加深我们对组合生成算法的理解,并教会我们如何在实际问题中应用这些算法。