问题描述
小C来到了一家饭馆,这里共有 n 道菜:
- 第
i道菜的价格为a[i]。 - 如果第
i道菜含有蘑菇,则s[i] = '1',否则s[i] = '0'。
小C希望点 k 道菜,并且:
- 总价格尽可能低;
- 所点菜中最多只能有
m道菜含有蘑菇。
输出满足条件的最小总价格,若无法满足条件则输出 -1。
示例分析
样例1
输入:
s = "001", a = [10, 20, 30], m = 1, k = 2
分析:
- 菜品信息:
- 菜1:无蘑菇,价格10;
- 菜2:无蘑菇,价格20;
- 菜3:有蘑菇,价格30。
- 需求:选2道菜,总价格最小,且最多1道菜有蘑菇。
策略:
- 按价格升序选择。
- 优先选择无蘑菇菜品(菜1和菜2)。
结果:选菜1和菜2,总价格为 10 + 20 = 30。
输出:30。
样例2
输入:
s = "111", a = [10, 20, 30], m = 1, k = 2
分析:
- 所有菜都含有蘑菇,无法满足“最多1道菜有蘑菇”的条件。
输出:-1。
样例3
输入:
s = "0101", a = [5, 15, 10, 20], m = 2, k = 3
分析:
- 菜品信息:
- 菜1:无蘑菇,价格5;
- 菜2:有蘑菇,价格15;
- 菜3:无蘑菇,价格10;
- 菜4:有蘑菇,价格20。
- 需求:选3道菜,总价格最小,且最多2道菜有蘑菇。
策略:
- 按价格升序选择。
- 优先选择无蘑菇的菜(菜1、菜3),再选一个有蘑菇的菜(菜2)。
结果:选菜1、菜3、菜2,总价格为 5 + 10 + 15 = 30。
输出:30。
解决思路
-
数据整理:
- 将每道菜的信息(是否含有蘑菇、价格)打包成元组:
(s[i], a[i])。 - 按价格升序排序。
- 将每道菜的信息(是否含有蘑菇、价格)打包成元组:
-
贪心策略:
- 遍历排序后的菜品列表,逐个选择。
- 优先选择无蘑菇的菜;如果无蘑菇的菜数量不足,再选择含有蘑菇的菜,但要满足蘑菇菜品限制。
-
边界处理:
- 如果无法满足选够
k道菜的条件,则返回-1。
- 如果无法满足选够
代码实现
def solution(s: str, a: list, m: int, k: int) -> int:
# 合并蘑菇信息和价格,并按价格排序
dishes = [(s[i], a[i]) for i in range(len(a))]
dishes.sort(key=lambda x: x[1])
total_cost = 0 # 总价格
selected_count = 0 # 已选菜品数量
mushroom_count = 0 # 已选蘑菇菜品数量
# 遍历排序后的菜品
for dish in dishes:
if selected_count < k: # 如果未选够菜
if dish[0] == '1': # 是蘑菇菜
if mushroom_count < m: # 如果蘑菇菜品未超限
total_cost += dish[1]
selected_count += 1
mushroom_count += 1
else: # 无蘑菇菜
total_cost += dish[1]
selected_count += 1
# 如果选不够 k 道菜,返回 -1
if selected_count < k:
return -1
return total_cost
if __name__ == '__main__':
# 示例测试
print(solution("001", [10, 20, 30], 1, 2) == 30) # 样例1
print(solution("111", [10, 20, 30], 1, 2) == -1) # 样例2
print(solution("0101", [5, 15, 10, 20], 2, 3) == 30) # 样例3
# 边界测试
print(solution("0", [10], 0, 1) == 10) # 仅有1道菜,无蘑菇
print(solution("1", [10], 0, 1) == -1) # 仅有1道菜,且含蘑菇但不允许
print(solution("101", [10, 15, 20], 1, 3) == -1) # 无法满足选够3道菜
print(solution("000", [5, 10, 15], 1, 3) == 30) # 全为无蘑菇菜
知识总结
- 贪心算法:
- 此题采用贪心策略:按价格升序选择,优先选择无蘑菇的菜。
- 列表排序与遍历:****
- list.sort(key=lambda x: x[1]) 可按特定字段排序,便于后续处理。
- 边界处理:****
- 确保选够 k 道菜,否则直接返回 -1。
工具运用:
-
使用AI刷题工具生成不同解法(如动态规划、回溯),对比学习。
-
针对错题,利用AI自动分析测试用例和逻辑漏洞,提高效率。
通过系统化的刷题练习和工具结合,逐步掌握贪心算法的核心思路和应用场景。