贪心 · 饭馆菜品选择问题(中) | 豆包MarsCode AI刷题

50 阅读7分钟

问题描述

小C来到了一家饭馆,这里共有 nn 道菜,第 ii 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 ii 道菜是否含有蘑菇。如果 s_i = '1',那么第 ii 道菜含有蘑菇,否则没有。

小C希望点 kk 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 mm 道菜含有蘑菇。小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


思路

目标:最低价购入 k道菜 并返回总价格,要求最多只有 m道有蘑菇的菜,无法满足则返回-1

  1. 统计有蘑菇和无蘑菇菜的数量
    • 将蘑菇的字符串转为整型数组
    • 并统计有蘑菇和无蘑菇菜的数量
  2. 检查是否满足条件
    • 当非蘑菇数小于k-m,则无法满足只有m道蘑菇菜的条件
  3. 创建菜品列表
    • 数据结构采用列表 存储存储每道菜的价格和蘑菇状态
  4. 按价格排序,选择菜品
    • 对菜品列表按价格进行排序
    • 遍历排序后菜品列表,选择满足条件的菜品,直到选满 k道菜
    • 若有蘑菇,当有蘑菇菜数小于m,则选;若无蘑菇,直接选

具体步骤

1. 统计蘑菇和非蘑菇菜的数量

  • 遍历 s 字符串,统计含有蘑菇和不含蘑菇的菜的数量。
    # 将字符串 s: str 转整型数组
    int_s = [int(char) for char in list(s)]

    count_no_mushroom = int_s.count(0)
    count_with_mushroom = int_s.count(1)
相关知识点
  • 整型数组名 = [int(char) for char in list(字符串名)] 将字符串转为整型数组
    • list(s) 将字符串s转为一个字符列表
    • int(char) 将每个字符转换为整数
    • for char in list(s) 遍历字符列表中的每个字符
    • ★★[int(char) for char in list(s)] 用列表生成式,将每个字符转换为整型,并生成一个新的整型数组
  • 列表名.count(元素) 统计列表中某内容的数量

2. 检查是否可能满足条件

  • 如果非蘑菇菜的数量小于 k−m,则无法满足条件,直接返回 -1
        if(count_no_mushroom < k - m):
            return -1
    

3. 创建菜品列表

  • 将每道菜的价格和蘑菇状态组合成一个元组列表。

        dishes = [(a[i], int_s[i]) for i in range(len(s))]   
    

4. 按价格排序

  • 使用 sort 方法按价格对菜品列表进行排序。

        dishes.sort(key=lambda x: x[0])
    
相关知识点
  • lambda匿名函数
    • lambda x: x[0] 提取每个元组的第一个元素,(本题 即价格)
    • key=___ 以___作为键
  • 列表名.sort()列表排序
  • dishes.sort(key=lambda x: x[0])dishes列表中的元素 按价格 进行升序排序,提取每个元素的第一个元素(此为 价格)作为排序的键

5. 选择菜品

  • 遍历排序后的菜品列表,选择满足条件的菜品,直到选满 k 道菜。

    • 如果某道菜含有蘑菇且当前已选择的蘑菇菜数量小于 m,则选择该菜。
    • 如果某道菜不含蘑菇,则直接选择该菜。
        # 初始化变量
        total_price = 0
        selected_mushroom = 0
        selected_count = 0
    
        # 选择菜品
        for price, has_mushroom in dishes:
            # 有蘑菇,且蘑菇菜的数量不超过m
            if has_mushroom == 1 and selected_mushroom < m:
                total_price += price
                selected_mushroom += 1
                selected_count += 1
    
            # 没有蘑菇的情况
            elif has_mushroom == 0:
                total_price += price
                selected_count += 1
    
            # 如果已选择k道菜,则停止
            if selected_count == k:
                break
    

6. 返回结果

  • 如果无法选满 k 道菜,返回 -1
  • 否则,返回总价格。

知识点整理

  1. 字符串处理

    • 字符串转换:将字符串 s 转换为整型数组 int_strint_str = [int(char) for char in list(s)]

    • 统计字符出现次数:使用 count 方法统计 0 的出现次数。 count_no_mushroom = int_str.count(0)

  2. 列表操作

    • 列表生成:使用列表生成式创建包含每道菜价格和蘑菇状态的元组列表。 dishes = [(a[i], int_str[i]) for i in range(len(s))]

    • 列表排序:使用 sort 方法按价格对列表进行排序。 dishes.sort(key=lambda x: x[0])

  3. 贪心算法

    • 核心思想:在每一步选择中,都选择当前最优的选项,以期望最终结果是最优的。
    • 应用场景:在本题中,我们希望在满足条件的情况下选择总价格最小的菜品。通过按价格排序,我们可以优先选择价格最低的菜品,从而逐步构建最优解。
  4. 遍历与选择

    • 核心思想:通过遍历数据集,选择满足条件的元素。
    • 应用场景:在本题中,我们遍历排序后的菜品列表,选择满足条件的菜品,直到选满 k 道菜

python方面

  • lambda x: x[0]匿名函数

    • lambda 是 Python 中的匿名函数(即没有名字的函数)。
    • 语法:lambda x: x[0] 定义了一个匿名函数,它接受一个参数 x(表示列表中的每个元组),并返回 x 的第一个元素 x[0]
    • ---->lambda 参数: 返回元素
  • 列表

    • 字符串s转换为列表:list(s)

    • 列表生成式:[expression for item in iterable]

      • 参数:expression表达式,item是从 iterable 中取出的每个元素,iterable可迭代对象(如列表、元组、字符串等)

      • 例子:创建包含多个元素的列表 dishes = [(a[i], int_list[i]) for i in range(len(s))]

    • 列表计数 count 方法:list.count(element)

      参数:list列表名称,element要计数的对象,即计算列表list中含有多少个element

    • 列表排序sort方法:list.sort(key=None, reverse=False)

      • 其中,key 参数是一个函数,用于从每个列表元素中提取一个用于排序的键; reverse 参数用于指定排序顺序,默认为 False(升序),如果设置为 True,则为降序。
      • 例子:dishes.sort(key=lambda x: x[0])

完整代码

from re import S


def solution(s: str, a: list, m: int, k: int) -> int:
    # 将字符串转整型数组
    int_s = [int(char) for char in list(s)]

    # 统计蘑菇和非蘑菇菜的数量
    count_no_mushroom = int_s.count(0)
    count_with_mushroom = int_s.count(1)

    # 应该有 k-m 道无蘑菇的,才可能满足条件---> 如果非蘑菇菜的数量小于 k-m,则无法满足条件
    if(count_no_mushroom < k - m):
        return -1

    # 创建列表,包含每道菜的价格和是否含有蘑菇的位置
    dishes = [(a[i], int_s[i]) for i in range(len(s))]
    
    # 按价格排序
    dishes.sort(key=lambda x: x[0])

    # 初始化变量
    total_price = 0
    selected_mushroom = 0
    selected_count = 0

    # 选择菜品
    for price, has_mushroom in dishes:
        # 有蘑菇,且蘑菇菜的数量不超过m
        if has_mushroom == 1 and selected_mushroom < m:
            total_price += price
            selected_mushroom += 1
            selected_count += 1

        # 没有蘑菇的情况
        elif has_mushroom == 0:
            total_price += price
            selected_count += 1

        # 如果已选择k道菜,则停止
        if selected_count == k:
            break
    if selected_count < k:
        return -1

    return total_price

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)


感受

豆包ai帮大忙,有思路但对python语法不熟悉,可以直接问他,具体问题具体分析,可以快速解决问题。好样的!!会ai提示词真的很重要,节省不少时间。语法知识蹭蹭蹭上升,实践中学习~~