问题:饭馆菜品选择问题
问题描述:
小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 道菜是否含有蘑菇。如果 s_i = '1',那么第 i 道菜含有蘑菇,否则没有。
小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 道菜含有蘑菇。小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);
}
}
代码解释
代码思路
-
分类菜品:
- 首先,我们需要将菜品分为两类:含蘑菇的和不含蘑菇的。
- 通过遍历菜品字符串
s,我们可以判断每道菜是否含有蘑菇,并将对应的价格分别存储在两个数组中:noMushroom和mushroom。
-
排序:
- 对这两类菜品的价格进行排序,从小到大。这样做的目的是为了在后续选择菜品时,能够优先选择价格较低的菜品。
-
动态选择最小的组合:
- 使用优先队列(PriorityQueue)来动态选择最小的组合。优先队列可以帮助我们高效地获取当前最小的总价格。
- 我们尝试不同的含蘑菇菜品数量,从0到最多
m道含蘑菇的菜品。对于每种含蘑菇菜品数量i,我们计算对应的组合总价格,并将其加入优先队列。
-
返回结果:
- 最后,从优先队列中取出最小的总价格。如果优先队列为空,说明无法满足条件,返回
-1。否则,返回优先队列中的最小值。
- 最后,从优先队列中取出最小的总价格。如果优先队列为空,说明无法满足条件,返回
详细步骤
-
初始化:
- 创建两个数组
noMushroom和mushroom,分别用于存储不含蘑菇和含蘑菇的菜品价格。 - 初始化两个计数器
noMushroomCount和mushroomCount,用于记录两类菜品的数量。
- 创建两个数组
-
分类菜品:
- 遍历菜品字符串
s,根据字符'0'或'1'将菜品价格分别存入noMushroom和mushroom数组中,并更新计数器。
- 遍历菜品字符串
-
排序:
- 对
noMushroom和mushroom数组进行排序,从小到大。
- 对
-
动态选择最小的组合:
- 创建一个优先队列
pq,用于存储不同组合的总价格。 - 遍历含蘑菇菜品数量
i,从0到m(或mushroomCount中的较小值)。 - 对于每个
i,检查是否可以选出k - i道不含蘑菇的菜品。如果可以,计算总价格并将其加入优先队列。
- 创建一个优先队列
-
返回结果:
- 如果优先队列为空,返回
-1,表示无法满足条件。 - 否则,返回优先队列中的最小值,即最小的总价格。
- 如果优先队列为空,返回