问题描述
小C来到了一家饭馆,这里共有 nn 道菜,第 ii 道菜的价格为 a_i
。其中一些菜中含有蘑菇,s_i
代表第 ii 道菜是否含有蘑菇。如果 s_i = '1'
,那么第 ii 道菜含有蘑菇,否则没有。
小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1
问题思路分析
这是一个组合优化问题,目标是从两类菜品中选择 k 道菜,使得总价格最低,并满足限制条件:至多选 m 道含蘑菇的菜。
关键点:
-
分组处理:
- 将菜品分为含蘑菇和不含蘑菇两类,便于分别排序和选择。
-
枚举选择:
- 枚举选择的含蘑菇菜品数量 x,剩余的 k−x 道菜必须从不含蘑菇菜品中选择。
-
排序贪心:
- 为了使总价格最低,优先选择价格最低的菜品(按价格排序后取前若干个)。
-
可行性检查:
- 确保所需的菜品数量 x 和 y=k−x 都能够从对应的菜品中取出。
算法步骤
-
将菜品分为两组:
- 含蘑菇的菜品:
with_mushroom
。 - 不含蘑菇的菜品:
without_mushroom
。
- 含蘑菇的菜品:
-
对两组分别按价格升序排序。
-
枚举含蘑菇的菜品数量 xx:
- 对于每个 xx,计算不含蘑菇的菜品数量 y=k−xy=k−x。
- 如果 x \leq \text{len(with_mushroom)} 且 y \leq \text{len(without_mushroom)},则计算总价格。
-
记录所有满足条件的方案中的最小价格。
-
如果无法找到任何满足条件的方案,返回 -1。
def solution(s: str, a: list, m: int, k: int) -> int:
n = len(a)
# 将菜品分为含蘑菇和不含蘑菇两类
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()
# 初始化结果
min_price = float('inf')
possible = False
# 枚举含蘑菇的菜品数量 x
for x in range(min(m, k) + 1): # x最多为m,且x不能超过k
y = k - x # 不含蘑菇的菜品数量
# 检查是否能挑选到足够的菜品
if x <= len(with_mushroom) and y <= len(without_mushroom):
# 计算当前组合的总价格
price = sum(with_mushroom[:x]) + sum(without_mushroom[:y])
min_price = min(min_price, price)
possible = True
# 如果找到了满足条件的方案,返回最小价格;否则返回-1
return min_price if possible else -1