说明:本篇笔记基于python语言写出
饭馆菜品选择问题
小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 i 道菜是否含有蘑菇。如果 s_i = '1',那么第 i 道菜含有蘑菇,否则没有。
小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1。
代码思路
做这道题首先要明白以下几点
-
分离含有蘑菇和不含有蘑菇的菜品:
- 遍历
s和a,将菜品按是否含有蘑菇分别存入no_mushroom和mushroom列表。
- 遍历
-
对两个列表按价格排序:
- 对
no_mushroom和mushroom按价格进行排序,以便后续选择价格最低的菜品。
- 对
-
遍历所有可能的组合:
- 遍历所有可能的含有蘑菇的菜品数量
i,从0到m。 - 对于每个
i,检查是否能从no_mushroom中选择k - i道菜。 - 计算当前组合的总价格,并更新最小总价格。
- 遍历所有可能的含有蘑菇的菜品数量
-
返回结果:
- 如果最小总价格没有更新,说明无法满足条件,返回
-1。 - 否则返回最小总价格。
- 如果最小总价格没有更新,说明无法满足条件,返回
答案
# 分离含有蘑菇和不含有蘑菇的菜品
no_mushroom = []
mushroom = []
for i in range(len(s)):
if s[i] == '0':
no_mushroom.append(a[i])
else:
mushroom.append(a[i])
# 对两个列表按价格排序
no_mushroom.sort()
mushroom.sort()
# 初始化最小总价格为无穷大
min_cost = float('inf')
# 遍历所有可能的组合
for i in range(min(m, len(mushroom)) + 1):
if k - i <= len(no_mushroom):
# 计算当前组合的总价格
current_cost = sum(mushroom[:i]) + sum(no_mushroom[:k-i])
# 更新最小总价格
min_cost = min(min_cost, current_cost)
# 如果最小总价格没有更新,说明无法满足条件
return -1 if min_cost == float('inf') else min_cost
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)
个人思考
做题时要注意以下问题
-
边界条件:
- 确保在遍历含有蘑菇的菜品数量
i时,i的取值范围是0到min(m, len(mushroom))。这是因为i不能超过m和mushroom列表的长度。 - 在计算
k - i时,确保k - i不超过no_mushroom列表的长度。
- 确保在遍历含有蘑菇的菜品数量
-
初始化最小总价格:
- 初始化
min_cost为float('inf'),表示初始状态下没有找到任何满足条件的组合。
- 初始化
-
排序:
- 对
no_mushroom和mushroom列表进行排序,以便能够选择价格最低的菜品。
- 对
总结
这道题涉及到了多个编程和算法相关的知识点,还需多多学习
1. 列表操作
- 列表的创建和遍历:通过遍历字符串
s和列表a,将菜品按是否含有蘑菇分别存入no_mushroom和mushroom列表。 - 列表的排序:使用
sort()方法对no_mushroom和mushroom列表按价格进行排序。
2. 条件判断
- 条件语句:使用
if语句来判断菜品是否含有蘑菇,并将其分类存入不同的列表。 - 边界条件判断:在遍历组合时,使用
if语句来检查是否能从no_mushroom中选择k - i道菜。
3. 循环
- for 循环:使用
for循环遍历所有可能的含有蘑菇的菜品数量i,从0到min(m, len(mushroom))。
4. 数学运算
- 求和:使用
sum()函数计算当前组合的总价格。 - 最小值更新:使用
min()函数更新最小总价格。
5. 排序算法
- 排序:虽然 Python 的
sort()方法内部使用了 Timsort 算法,但理解排序的基本概念和复杂度分析是重要的。
6. 贪心算法
- 贪心策略:通过排序和选择价格最低的菜品,尽可能地降低总价格,这是一种贪心策略。
7. 动态规划(可选)
- 动态规划思想:虽然这道题没有显式地使用动态规划,但遍历所有可能的组合并选择最优解的思想与动态规划类似。
8. 边界处理
- 无穷大初始化:使用
float('inf')初始化最小总价格,表示初始状态下没有找到任何满足条件的组合。 - 返回结果:如果最小总价格没有更新,说明无法满足条件,返回
-1。