饭馆菜品选择问题
问题描述
小C来到了一家饭馆,这里共有 道菜,第 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 道菜是否含有蘑菇。如果 s_i = '1',那么第 道菜含有蘑菇,否则没有。
小C希望点 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 道菜含有蘑菇。小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
解题思路
1. 问题理解
首先,我们需要理解问题的核心要求:
- 小C希望点 道菜,且总价格尽可能低。
- 小C最多能接受 道含有蘑菇的菜。
也就是说我们需要在选择小于等于 道含有蘑菇的菜的前提下,选择价格最低的 道菜。
2. 数据结构选择
为了方便处理,我们可以将每道菜的信息存储在一个列表中,每个元素包含菜的索引、价格和是否含有蘑菇的信息。例如:
dishes = [(i, a[i], s[i] == '1') for i in range(len(s))]
3. 算法步骤
-
排序:
- 根据价格对
dishes列表进行从小到大排序,以便优先选择价格较低的菜。
- 根据价格对
dishes.sort(key=lambda x: x[1])
-
选择菜品:
-
初始化
total_price用于记录总价格,初始值为 0。 -
初始化
mushroom_count用于记录当前选择的含有蘑菇的菜的数量,初始值为 0。 -
遍历排序后的
dishes,尝试选择k道菜:- 如果当前菜含有蘑菇且
mushroom_count已经达到m,则跳过该菜。 - 否则,选择该菜,更新
total_price和mushroom_count。
- 如果当前菜含有蘑菇且
-
如果成功选择了
k道菜,则返回total_price,否则返回-1。
-
4. 代码实现
def solution(s: str, a: list, m: int, k: int) -> int:
# 将菜的索引、价格和是否含有蘑菇的信息存储在列表中
dishes = [(i, a[i], s[i] == '1') for i in range(len(s))]
# 根据价格对列表进行排序
dishes.sort(key=lambda x: x[1])
total_price = 0
mushroom_count = 0
selected_count = 0
for dish in dishes:
if dish[2] and mushroom_count >= m:
continue
total_price += dish[1]
if dish[2]:
mushroom_count += 1
selected_count += 1
if selected_count == k:
return total_price
return -1
复杂度分析
- 时间复杂度:排序的时间复杂度为 ,遍历
dishes的时间复杂度为 。因此,总的时间复杂度为 。 - 空间复杂度:我们使用了一个额外的列表
dishes来存储菜的信息,因此空间复杂度为 。
总结
通过将菜的信息存储在一个列表中并根据价格进行排序,我们可以有效地选择满足条件的菜品,并计算出最小总价格。这个方法不仅简单易懂,而且在时间复杂度和空间复杂度上都表现良好。
在实际编程中,我们还需要注意边界条件的处理,例如当 k 大于菜的总数时,直接返回 -1。此外,对于含有蘑菇的菜的数量限制,我们需要在遍历过程中进行严格的检查,以确保满足小C的要求。
通过这个问题的解决,我们可以看到排序和贪心算法在解决优化问题中的强大作用。