饭馆菜品选择问题 | 豆包MarsCode AI刷题

113 阅读3分钟

问题描述

小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

解题思路

  1. 分类菜品

    • 根据 s[i] 的值,将菜品分为两组:

      • 蘑菇菜mushrooms,满足 s[i]=′1′。
      • 非蘑菇菜noMushrooms,满足 s[i]=′0′。
  2. 排序

    • 对两组菜品分别按照价格升序排序,优先选取价格最低的菜品。
  3. 枚举蘑菇菜的选择数量

    • xxx:从 mushrooms 中选择的菜的数量,范围是 [0,min⁡(k,m)]。
    • noMushrooms 中选择 k−x 道菜。
  4. 验证组合可行性

    • 检查蘑菇菜或非蘑菇菜的数量是否足够满足当前选择。如果不足,跳过该组合。
  5. 计算总价格

    • mushrooms 中选前 x 个菜,从 noMushrooms 中选前 k−x 个菜,计算总价格。
  6. 输出结果

    • 遍历所有组合,记录最低总价格。如果无法满足条件,返回 −1。

Java代码实现

java
复制代码
import java.util.*;

public class Main {
    public static long solution(String s, int[] a, int m, int k) {
        List<Integer> mushrooms = new ArrayList<>();
        List<Integer> noMushrooms = new ArrayList<>();

        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '1') {
                mushrooms.add(a[i]);
            } else {
                noMushrooms.add(a[i]);
            }
        }

        Collections.sort(mushrooms);
        Collections.sort(noMushrooms);

        long minCost = Long.MAX_VALUE;
        boolean found = false;

        for (int x = 0; x <= Math.min(k, m); x++) {
            int y = k - x; 

            if (x > mushrooms.size() || y > noMushrooms.size()) {
                continue;
            }

            long cost = 0;
            for (int i = 0; i < x; i++) {
                cost += mushrooms.get(i);
            }
            for (int i = 0; i < y; i++) {
                cost += noMushrooms.get(i);
            }

            minCost = Math.min(minCost, cost);
            found = true;
        }

        return found ? minCost : -1;
    }

    public static void main(String[] args) {
        System.out.println(solution("001", new int[]{10, 20, 30}, 1, 2) == 30); 
        System.out.println(solution("111", new int[]{10, 20, 30}, 1, 2) == -1); 
        System.out.println(solution("0101", new int[]{5, 15, 10, 20}, 2, 3) == 30); 
    }
}

代码说明

  1. 分类和排序

    • 将含有蘑菇的菜和不含蘑菇的菜分别存入两个列表 mushroomsnoMushrooms
    • 对两个列表按价格升序排序,方便后续优先选择价格最低的菜品。
  2. 枚举蘑菇菜数量

    • 遍历 x(选择的蘑菇菜数量),根据 y=k−x 计算需要的非蘑菇菜数量。
    • 如果 x > mushrooms.size() 或 y > noMushrooms.size(),说明当前组合不可行,跳过。
  3. 计算总价格

    • mushroomsnoMushrooms 分别选择前 x 和 y 道菜,计算总价格并更新全局最小值。
  4. 输出结果

    • 如果找到符合条件的组合,返回最低总价格。
    • 如果所有组合都不符合条件,返回 −1。

复杂度分析

  1. 时间复杂度

    • 分类菜品:O(n)。
    • 排序:O(nlog⁡n)。
    • 枚举组合并计算价格:O(k^2),其中 k 是最多选择的菜品数量。
    • 总复杂度:O(nlog⁡n + k^2)。
  2. 空间复杂度

    • 使用了两个额外的列表存储菜品,空间复杂度为 O(n)。

总结

  • 分类和排序是解决该问题的核心,通过排序优先选取价格最低的菜品。
  • 通过穷举组合,验证所有可能的选择,确保找到最低总价格。
  • 该方法时间复杂度较低,适合处理常见规模的输入。