一、问题描述
某商场有 Ⅳ 件商品,其中第之件的价格是 4:。现在该商场正在进行“买二赠一”的优惠活动,具体规则是:每购买 2 件商品,假设其中较便宜的价格是 P(如果两件商品价格一样,则 P 等于其中一件商品的价格),就可以从剩余商品中任选一件价格不超过号的商品,免费获得这一件商品。可以通过反复购买2件商品来获得多件免费商品,但是每件商品只能被购买或免费获得一次。
小明想知道如果要拿下所有商品(包含购买和免费获得),至少要花费多少钱?
输入格式
第一行包含一个整数 N。
第二行包含 N 个整数,代表 A1,A2,A3,...,AN。
输出格式
输出一个整数,代表答案。
样例说明
小明可以先购买价格 4和8 的商品,免费获得一件价格为 1 的商品;再后买价格为5和7的商品,免费获得价格为2的商品;最后单独购买剩下的一件价格为1的商品。总计花费4+8+5 +7+1-25。不存在花费更低的方案。
二、解题思路
根据题目可知我们需要保存两次购买后的比较小的值的一半,然后去选择一个商品免费带走。刚开始作者也想不到怎么做,于是给他们的价格从小到大排序放入一个数组中,然后发现从后面买前面的可以免费,于是乎我就开始便利数组,引入一个队列,用于存储免费的额度大小。所以呢,没两次购买后进入一个免费购买的额度,如果原数组有比这个小的值,那么直接往前计数,不用算该商品价格。然后队列的元素要出队,这样子就能穷尽所有的元素并且拿到最少的花费结果。
package 蓝桥杯备赛;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.concurrent.ConcurrentLinkedQueue;
public class 买二赠一 {
public static void main(String[] args) {
//写入数据
Scanner scan = new Scanner(System.in);
int number;
number = scan.nextInt();
int price[] = new int[number];
for(int i=0;i<number;i++) {
price[i] = scan.nextInt();
}
long res = 0;
scan.close();
Arrays.sort(price);
int t = number-1;
Queue<Integer> queue = new LinkedList<>();
boolean flag = false;
while(t>=0) {
if(!queue.isEmpty()&&price[t]<=queue.peek()) {//如果队列非空且价格小于队列的第一个元素。queue.peek只会获取队列头部元素,不会删除。
queue.poll();//出队列
}
else {
if(flag) {
queue.add(price[t]/2);
flag = false;
}
else {
flag = true;
}
res += price[t];
}
t--;
}
System.out.print(res);
}
}
三、总结
作者从这题中学到了很多比如队列(栈)的一些应用 如:Queue<Integer> queue = new LinkedList<>();可以建立一个新的队列,poll是出栈0,add是进栈,然后peek是获取头号元素,这里res用了long是为了防止数据过大溢出,以后的答案都写long,防止被坑。
蓝桥要加油了没多少时间准备了