青训营X豆包MarsCode技术训练营第五课 | 豆包MarsCode AI 刷题

136 阅读3分钟

问题:饭馆菜品选择问题

问题描述:

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

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

代码实现

import java.util.Arrays;
import java.util.PriorityQueue;

public class Main {
    public static long solution(String s, int[] a, int m, int k) {
        // 将菜品分为两类:含蘑菇的和不含蘑菇的
        int n = s.length();
        int[] noMushroom = new int[n];
        int[] mushroom = new int[n];
        int noMushroomCount = 0, mushroomCount = 0;

        for (int i = 0; i < n; i++) {
            if (s.charAt(i) == '0') {
                noMushroom[noMushroomCount++] = a[i];
            } else {
                mushroom[mushroomCount++] = a[i];
            }
        }

        // 对两类菜品分别进行排序,从小到大
        Arrays.sort(noMushroom, 0, noMushroomCount);
        Arrays.sort(mushroom, 0, mushroomCount);

        // 使用优先队列来动态选择最小的组合
        PriorityQueue<Long> pq = new PriorityQueue<>();

        // 尝试不同的含蘑菇菜品数量
        for (int i = 0; i <= Math.min(m, mushroomCount); i++) {
            if (k - i <= noMushroomCount) {
                long sum = 0;
                for (int j = 0; j < i; j++) {
                    sum += mushroom[j];
                }
                for (int j = 0; j < k - i; j++) {
                    sum += noMushroom[j];
                }
                pq.offer(sum);
            }
        }

        // 返回最小的总价格,如果无法满足条件则返回-1
        return pq.isEmpty() ? -1 : pq.poll();
    }

    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. 分类菜品

    • 首先,我们需要将菜品分为两类:含蘑菇的和不含蘑菇的。
    • 通过遍历菜品字符串 s,我们可以判断每道菜是否含有蘑菇,并将对应的价格分别存储在两个数组中:noMushroommushroom
  2. 排序

    • 对这两类菜品的价格进行排序,从小到大。这样做的目的是为了在后续选择菜品时,能够优先选择价格较低的菜品。
  3. 动态选择最小的组合

    • 使用优先队列(PriorityQueue)来动态选择最小的组合。优先队列可以帮助我们高效地获取当前最小的总价格。
    • 我们尝试不同的含蘑菇菜品数量,从0到最多 m 道含蘑菇的菜品。对于每种含蘑菇菜品数量 i,我们计算对应的组合总价格,并将其加入优先队列。
  4. 返回结果

    • 最后,从优先队列中取出最小的总价格。如果优先队列为空,说明无法满足条件,返回 -1。否则,返回优先队列中的最小值。

详细步骤

  1. 初始化

    • 创建两个数组 noMushroommushroom,分别用于存储不含蘑菇和含蘑菇的菜品价格。
    • 初始化两个计数器 noMushroomCountmushroomCount,用于记录两类菜品的数量。
  2. 分类菜品

    • 遍历菜品字符串 s,根据字符 '0''1' 将菜品价格分别存入 noMushroommushroom 数组中,并更新计数器。
  3. 排序

    • noMushroommushroom 数组进行排序,从小到大。
  4. 动态选择最小的组合

    • 创建一个优先队列 pq,用于存储不同组合的总价格。
    • 遍历含蘑菇菜品数量 i,从0到 m(或 mushroomCount 中的较小值)。
    • 对于每个 i,检查是否可以选出 k - i 道不含蘑菇的菜品。如果可以,计算总价格并将其加入优先队列。
  5. 返回结果

    • 如果优先队列为空,返回 -1,表示无法满足条件。
    • 否则,返回优先队列中的最小值,即最小的总价格。