问题描述
小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
这是一个典型的组合优化问题,涉及到按条件筛选和最优解的计算。我们可以将问题分为以下几个步骤:
- 将菜品分类 根据是否含有蘑菇,将所有菜品分为两类: 含蘑菇的菜品使用一个数组存储价格,不含蘑菇的菜品使用另一个数组存储价格。 这个分类的目的是方便后续操作时按条件选择菜品。
- 优化选择菜品 选择k道菜的核心是枚举组合: 枚举选择x道含蘑菇的菜品,要求x≤m 且x ≤含蘑菇菜品的总数。剩余y=k−x道菜必须从不含蘑菇的菜品中选择,要求y ≤不含蘑菇菜品的总数 y≤不含蘑菇菜品的总数。
- 按价格排序为了让总价格尽可能低,可以对两组菜品的价格分别升序排序。这种贪心策略保证了我们每次都能优先选择价格最低的菜品。
- 枚举并计算总价格 对于每种x和y的组合:(1)取含蘑菇菜品价格中最便宜的x个。(2)取不含蘑菇菜品价格中最便宜的y个。(3)计算总价格,并与当前最小总价格比较,保留较小值。 如果枚举结束后,无法找到满足条件的组合,则输出-1。
- 特例处理 在以下两种情况下需要特殊处理:(1)菜品总数不足k:如果两组菜品加起来不足k道,直接输出 -1。(2)蘑菇限制过严:如果m限制过小导致无法满足x+y=k,也输出 -1。
python
def solution(s: str, a: list, m: int, k: int) -> int:
# 将菜品分组
mushroom = []
non_mushroom = []
for i in range(len(s)):
if s[i] == '1':
mushroom.append(a[i])
else:
non_mushroom.append(a[i])
# 排序以便选择价格最低的菜品
mushroom.sort()
non_mushroom.sort()
# 如果菜品总数不足 k 道,直接返回 -1
if len(mushroom) + len(non_mushroom) < k:
return -1
# 枚举含蘑菇菜品的数量
min_cost = float('inf')
for x in range(0, min(k, m) + 1): # x 为选择的含蘑菇菜品数量
y = k - x # y 为选择的不含蘑菇菜品数量
# 如果不够选,跳过
if x > len(mushroom) or y > len(non_mushroom):
continue
# 计算当前组合的总价格
cost = sum(mushroom[:x]) + sum(non_mushroom[:y])
min_cost = min(min_cost, cost)
return min_cost if min_cost != 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)