承接上文:2023年第十四届蓝桥杯JavaB组省赛真题及全部解析(下)。
目录
题目来自:蓝桥杯官网
七、试题 G:买二赠一
• 题目分析:
因为每次我们要尽可能的使免费拿走商品的价格尽可能的大,但是免费的金额又与较便宜的物品有关,这是一道贪心题(猜的,比赛想到就可以写了,贪心的证明是非常恶心的)。
• 解题思路:
1. 排序商品价格(降序)。
2. 使用队列来存储免费的金额。
3. 遍历全部商品,遇到能免费的商品(小于队列队头元素),出队列,这个商品跳过(不加到总和)。其他的正常遍历,加到总和。
4. 一旦选了两个商品,将后面选的(肯定小于前面选的)一半价格加入队列。
5. 返回结果。
如果下面的排序写法看不懂的话,可以去看我之前写的Java sort 详解,里面都有写到。
• 代码编写:
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
//读入数据
Integer[] arr = new Integer[n];
for(int i = 0;i < n;i++){
arr[i] = in.nextInt();
}
Arrays.sort(arr,(o1,o2) -> {//从大到小排序
return o1 >= o2 ? -1 : 1;//或者(o2 - o1)
});
long sum = 0;//存储总花费
Queue<Integer> q = new LinkedList<>();//存储可以免费的金额,保证是先进先出
int count = 0;//记录何时到达二次
for(int i = 0;i < n;i++){
if(!q.isEmpty() && q.peek() >= arr[i]) {//说明可以免费带走
q.poll();//队头免费金额用过了,把队头弹出去。
continue;//跳过这个商品
}
sum += arr[i];
count++;
if(count == 2){
count = 0;
q.add(arr[i] / 2);//可以免费的金额,存入队列
}
}
System.out.println(sum);
}
}
• 运行结果:
八、试题 H:合并石子
• 题目分析:
这是一道区间 dp 的问题,关于区间 dp 可能平时会遇到的比较少。如果不了解的话,建议先去看看区间 dp,再去洛谷把