问题描述
小C来到了一家饭馆,这里共有道菜,第 道菜的价格为ai。其中一些菜中含有蘑 菇,si代表第道菜是否含有蘑菇。如果 s1='1',那么第道菜含有蘑菇,否则 没有。
小C希望点道菜,且希望总价格尽可能低。 由于她不喜欢蘑菇,她希望所点的菜中最多只 有道菜含有蘑菇。小C想知道在满足条件 的情况下能选出的最小总价格是多少。如果无 法按照要求选择菜品,则输出-1。
测试样例
样例1:
输入:s="001",a=[10,20,30],m=1,k=2
输出:30
问题理解
你需要从 n 道菜中选择 k 道菜,使得总价格最小,并且最多只能选择 m 道含有蘑菇的菜。如果无法满足条件,则返回 -1。
解题思路
-
数据结构选择:
- 使用一个列表
dishes来存储每道菜的价格和是否含有蘑菇的标记。 - 列表中的每个元素是一个包含两个整数的数组
[价格, 是否含蘑菇]。
- 使用一个列表
-
排序:
- 按照价格从小到大对
dishes进行排序。这样可以优先选择价格较低的菜品。
- 按照价格从小到大对
-
选择菜品:
- 遍历排序后的
dishes列表,按照价格从小到大的顺序选择菜品。 - 使用两个计数器:
mushroomCount记录已选择的含有蘑菇的菜品数量,selectedCount记录已选择的菜品总- - 数。 - 如果当前菜品含有蘑菇且
mushroomCount未达到m,则选择该菜品。 - 如果当前菜品不含蘑菇,则直接选择该菜品。
- 如果已选满
k道菜,则停止选择。
- 遍历排序后的
-
返回结果:
- 如果已选满
k道菜,返回总价格。 - 否则返回
-1,表示无法满足条件。
- 如果已选满
代码展示
import java.util.Comparator;
import java.util.List;
public class Main {
public static long solution(String s, int[] a, int m, int k) {
// write code here
List<int[]> dishes = new ArrayList<>();
// 将每道菜的价格及其是否含蘑菇的标记存入dishes
for (int i = 0; i < s.length(); i++) {
dishes.add(new int[]{a[i], s.charAt(i) == '1' ? 1 : 0}); // [价格, 是否含蘑菇]
}
// 按照价格从小到大排序
dishes.sort(Comparator.comparingInt(d -> d[0]));
long totalCost = 0;
int mushroomCount = 0;
int selectedCount = 0;
// 遍历排序后的菜品
for (int[] dish : dishes) {
// 如果还没有选满k道菜
if (selectedCount < k) {
// 如果菜品含蘑菇,检查蘑菇菜品数量是否超出限制
if (dish[1] == 1) {
if (mushroomCount < m) {
totalCost += dish[0]; // 选择该蘑菇菜
mushroomCount++;
selectedCount++;
}
} else {
totalCost += dish[0]; // 选择该非蘑菇菜
selectedCount++;
}
} else {
break;
}
}
// 如果选满了k道菜,返回最小的总价格,否则返回-1
return selectedCount == k ? totalCost : -1;
}
总结
这段代码的主要思路是通过贪心算法,按照价格从小到大的顺序选择菜品,同时确保所选菜品中最多只有 m 道含有蘑菇的菜品。如果能够选满 k 道菜,则返回总价格;否则返回 -1。