刷题(3) | 豆包MarsCode AI刷题

2 阅读4分钟

问题描述

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

小C希望点 𝑘k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 𝑚m 道菜含有蘑菇。小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. 分类菜品并排序
  • 将所有菜品分为两类:不含蘑菇的菜品 (S) 和 含蘑菇的菜品 (M)
  • 将不含蘑菇的菜品和含蘑菇的菜品分别按价格从低到高排序。
  1. 序列和计算
  • 为了快速计算任意数量菜品的总价格,计算两类菜品的序列和:
    • prefix_S[i] 表示从不含蘑菇的菜品中选择前 i 道菜的总价格。
    • prefix_M[i] 表示从含蘑菇的菜品中选择前 i 道菜的总价格。
  1. 尝试不同的蘑菇菜品数量
  • 小C可以选择从 0 到 min(m, len(M), k) 道含蘑菇的菜品。
  • 对于每一个可能的选择 t (含蘑菇的菜品数量):
    • 检查不含蘑菇的菜品数量是否足够 k - t
    • 计算选择 t 道含蘑菇的菜品和 k - t 道不含蘑菇的菜品的总价格。
    • 记录所有可能选择中的最小总价格。
    • 如果无法找到满足条件的组合(例如,所需的不含蘑菇的菜品数量超过实际可选数量),则返回 -1

算法流程

  • 分类和排序

    • 遍历所有菜品,将其分为含蘑菇和不含蘑菇两类。
    • 分别对这两类菜品按价格升序排序。
  • 计算序列和

    • 分别计算不含蘑菇和含蘑菇的菜品的序列和,以便快速计算任意数量菜品的总价格。
  • 遍历可能的蘑菇菜品数量

    • 对于每一个可能的 t (含蘑菇的菜品数量),计算对应的不含蘑菇的菜品数量。
    • 检查是否满足选择条件,如果满足则计算总价格并更新最小值。
  • 返回结果

    • 如果找到至少一种满足条件的组合,返回最小总价格。
    • 否则,返回 -1

代码实现

def solution(s: str, a: list, m: int, k: int) -> int:
    # 将菜品分为不含蘑菇和含蘑菇两类
    S = []  # 不含蘑菇的菜品价格
    M = []  # 含蘑菇的菜品价格

    for si, ai in zip(s, a):
        if si == '0':
            S.append(ai)
        else:
            M.append(ai)

    # 对两类菜品按价格升序排序
    S.sort()
    M.sort()

    # 计算前缀和,以便快速计算任意数量菜品的总价格
    prefix_S = [0]  # prefix_S[i] 表示前 i 道不含蘑菇菜品的总价格
    for price in S:
        prefix_S.append(prefix_S[-1] + price)

    prefix_M = [0]  # prefix_M[i] 表示前 i 道含蘑菇菜品的总价格
    for price in M:
        prefix_M.append(prefix_M[-1] + price)

    min_total = None  # 用于记录最小总价格

    # 尝试不同数量的含蘑菇菜品
    max_t = min(m, len(M), k)  # t 不能超过 m、含蘑菇菜品的数量和 k
    for t in range(0, max_t + 1):
        required_S = k - t  # 需要的不含蘑菇菜品数量

        if required_S <= len(S):
            total = prefix_M[t] + prefix_S[required_S]
            if (min_total is None) or (total < min_total):
                min_total = total

    # 返回结果
    if min_total is not None:
        return min_total
    else:
        return -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)

总结

通过将菜品分类、排序并利用序列和的方式,能够高效地找到满足条件的最小总价格。关键在于合理地将问题分解为两类菜品,并通过遍历不同的含蘑菇菜品数量来寻找最优解。