饭馆菜品选择问题
问题描述
小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。
算法步骤
-
边界条件检查:
- 如果
k大于菜的总数n,或者m小于 0,直接返回-1。
- 如果
-
生成所有可能的组合:
- 使用组合生成算法(如递归或迭代)生成所有可能的
k道菜的组合。
- 使用组合生成算法(如递归或迭代)生成所有可能的
-
计算每个组合的总价格和蘑菇数量:
- 对于每个组合,计算总价格和蘑菇数量。
- 如果蘑菇数量不超过
m,则更新最小总价格。
-
返回结果:
- 如果找到了满足条件的组合,返回最小总价格;否则返回
-1。
- 如果找到了满足条件的组合,返回最小总价格;否则返回
具体步骤
-
初始化最小总价格为无穷大。
-
生成所有可能的
k道菜的组合:- 使用递归或迭代生成所有可能的组合。
-
对于每个组合:
- 计算总价格。
- 计算蘑菇数量。
- 如果蘑菇数量不超过
m,则更新最小总价格。
-
返回最小总价格,如果没有满足条件的组合则返回
-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)(即从0到n - 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_price和price_sum中的较小值作为新的min_price。
- 通过列表推导式
-
最后,判断
min_price是否还是正无穷大,如果是则表示没有找到满足条件的组合,返回-1;否则返回计算得到的最小价格min_price。
-
-
这道题考察了组合生成、条件筛选和最小值查找等基本算法思想。通过这道题,可以加深我们对组合生成算法的理解,并教会我们如何在实际问题中应用这些算法。