Java蓝桥杯备赛3.11(买二赠一)

一、问题描述


某商场有 Ⅳ 件商品,其中第之件的价格是 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,防止被坑。

        蓝桥要加油了没多少时间准备了

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱笨笨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值