“蘑菇菜品选择问题”解决方案 | 豆包MarsCode AI刷题

91 阅读5分钟

基于豆包MarsCode训练营总结的“蘑菇菜品选择问题”解决方案

在参加豆包MarsCode技术训练营的过程中,我逐步理解并掌握了如何将算法思想应用于具体的编程题目解决中。今天,我将通过分析一个典型的编程问题——“蘑菇菜品选择问题”,总结在解决此问题过程中获得的经验、思考与技术要点,帮助其他同学更好地理解问题的本质,并提供一些学习建议。

问题分析

题目要求我们帮助小C从若干道菜品中选择合适的菜品,使得满足以下条件:

  1. 选择的菜品总数为 k
  2. 最多选择 m 道含有蘑菇的菜品。
  3. 在满足上述条件的前提下,选择的菜品的总价格最小。

如果无法满足选择 k 道菜且最多只有 m 道菜含蘑菇的条件,则返回 -1。

对于此问题,直观的解决思路是:

  • 我们需要从总共的菜品中选择 k 道菜,且在这 k 道菜中,含有蘑菇的菜品不能超过 m 道。
  • 同时,选择的菜品总价格应尽可能低。

思路和分析

从算法角度看,问题可以分解为几个子问题:

  1. 如何选择菜品:我们需要从菜品中挑选出价格最低的 k 道菜,且在这些菜品中含有蘑菇的数量不能超过 m
  2. 如何有效地进行选择:我们可以将所有菜品按照价格升序排序,先选价格低的菜品,以保证总价格最小。

在考虑了这些子问题之后,我设计了一个解决方案:先将菜品按价格排序,然后尝试不同的包含蘑菇菜品的数量,逐步判断能否找到符合条件的 k 道菜。

代码实现

以下是我在训练营中解决该问题的代码实现:

def solution(s: str, a: list, m: int, k: int) -> int:
    # 将菜品按价格排序,并记录是否含有蘑菇
    dishes = sorted(zip(s, a), key=lambda x: x[1])
    
    # 初始化最小总价格
    min_price = float('inf')
    
    # 尝试选择含有蘑菇的菜品数量从0到m
    for mushrooms in range(m + 1):
        # 选择含有蘑菇的菜品数量为mushrooms
        selected_dishes = []
        non_mushroom_count = 0
        
        for dish in dishes:
            if dish[0] == '1' and mushrooms > 0:
                selected_dishes.append(dish[1])
                mushrooms -= 1
            elif dish[0] == '0':
                selected_dishes.append(dish[1])
                non_mushroom_count += 1
            
            # 如果已经选择了k道菜,停止选择
            if len(selected_dishes) == k:
                break
        
        # 如果选择的菜品数量等于k,计算总价格
        if len(selected_dishes) == k:
            min_price = min(min_price, sum(selected_dishes))
    
    # 如果无法选择k道菜,返回-1
    return min_price if min_price != 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)

代码分析

  1. 数据预处理

    • 首先,将菜品的蘑菇信息 (s) 和价格 (a) 配对,并根据价格对菜品进行排序。这样做的目的是为了优先选择价格较低的菜品,尽可能地控制总花费。
  2. 遍历所有可能的蘑菇菜品数量

    • 我们通过 for mushrooms in range(m + 1) 来尝试选择不同数量的蘑菇菜品。在每一次尝试中,我们从排序后的菜品中选择菜品,优先选择价格最低的菜品。
    • 每次选择时,首先检查是否可以选择含蘑菇的菜品(即 dish[0] == '1'),如果可以且剩余的蘑菇数大于0,则选这道菜。如果选择的是不含蘑菇的菜品,则直接选择。
  3. 边界条件和返回值

    • 如果选择的菜品数目达到了 k,则计算当前的总价格,并更新最小价格。
    • 如果遍历结束后,无法选择到满足条件的 k 道菜品,则返回 -1。

学习思考与总结

在这道题的解决过程中,我学习到了几个重要的编程思想和技巧:

  1. 贪心算法的应用

    • 本题的核心是从菜品中选择价格最低的 k 道菜,并且考虑蘑菇的数量限制。使用贪心算法(即每次都选价格最小的菜品)是非常有效的策略,因为这样可以确保在每一次选择中都尽量减少总价格。
  2. 排序与筛选

    • 排序是解决此类最优化问题的常用手段。通过将菜品按照价格排序,我们能够优先选取价格最小的菜品,从而确保总价格最小。
  3. 边界条件的处理

    • 在设计解决方案时,边界条件的考虑至关重要。例如,如何处理菜品数不足 k 道,或者无法满足蘑菇数量限制的情况。这些边界条件必须在代码中进行专门的处理,否则可能导致错误的结果。

对其他入门同学的学习建议

  1. 理解问题的核心要求:在面对编程题时,首先要清楚题目给出的要求和限制条件,然后分析是否可以通过排序、贪心、动态规划等常见算法来优化问题的求解过程。

  2. 从基础算法入手:对于刚接触编程的同学,理解并掌握基本的算法思想(如排序、递归、贪心算法等)是非常重要的。这些基础的算法技巧会在后续的题目中不断复用。

  3. 多做题,勤总结:编程技能的提升离不开多做题和总结。在每做完一道题后,思考自己是否有更好的解法,或者对当前解法是否可以进行优化。不断积累经验,提升解题思维。

结语

通过这次的编程题目,我不仅提升了自己的编码能力,还加深了对贪心算法和排序等基本算法思想的理解。希望我的总结能够帮助其他同学在面对类似问题时,能够更加高效地思考并给出合适的解决方案。同时,面对不同类型的编程题目时,保持冷静和细致思考,也是解决问题的关键。