第十四届蓝桥杯JavaB组G题----买二赠一

目录

【问题描述】

【输入格式】

【输出格式】

【样例输入】

【样例输出】

【样例说明】

【评测用例规模与约定】

【我的想法】

【我的代码】

【代码的运行结果】

【代码的思想与解释说明】


GitHub算法详细代码(多届比赛的多个算法题):yhbn/algorithm (github.com)icon-default.png?t=N7T8https://github.com/yhbn/algorithm

【问题描述】

某商场有 N 件商品,其中第 i 件的价格是 A i 。现在该商场正在进行 “ 买二 赠一” 的优惠活动,具体规则是: 每购买 2 件商品,假设其中较便宜的价格是 P (如果两件商品价格一样,
则 P 等于其中一件商品的价格),就可以从剩余商品中任选一件价格不超过 P /2 的商品,免费获得这一件商品。可以通过反复购买 2 件商品来获得多件免费商 品,但是每件商品只能被购买或免费获得一次。 小明想知道如果要拿下所有商品(包含购买和免费获得),至少要花费多少钱?

【输入格式】

第一行包含一个整数 N 。
第二行包含 N 个整数,代表 A 1 , A 2 , A 3 , . . . , A N

【输出格式】

输出一个整数,代表答案。

【样例输入】

7
1 4 2 8 5 7 1

【样例输出】

25

【样例说明】

小明可以先购买价格 4 和 8 的商品,免费获得一件价格为 1 的商品;再后
买价格为 5 和 7 的商品,免费获得价格为 2 的商品;最后单独购买剩下的一件
价格为 1 的商品。总计花费 4 + 8 + 5 + 7 + 1 = 25 。不存在花费更低的方案。

【评测用例规模与约定】

对于 30 % 的数据, 1 ≤ N ≤ 20 。
对于 100 % 的数据, 1 ≤ N ≤ 5 × 10⁵ ,1 ≤ A i ≤ 10⁹ 。

【我的想法】

利用贪心的思想,首先把数组排序,买两个最贵的东西,然后得到最大的免单额度,去换可以换到的最贵的东西,把买到的东西和换到的东西的价格在原价格数组设置成0即可

【我的代码】

import java.util.Arrays;
import java.util.Scanner;

public class test7 {
    Scanner scanner = new Scanner(System.in);
    int N = scanner.nextInt();

    void zuixiaokaizhi() {
        int a[] = new int[N];
        for (int j = 0; j < N; j++) {
            a[j]=scanner.nextInt();
        }
        Arrays.sort(a);
        int money = 0;
        int m = 0, n = 0;
        int remain=0;
        while (m==0||n==0){
            for (int j = 1; j <= N; j++) {
                if (a[N - j] != 0) {
                    if (m==0){
                        m=a[N-j];
                        a[N - j] = 0;
                    }
                    else if (n==0){
                        n=a[N-j];
                        a[N - j] = 0;
                    }
                    if (m*n!=0) break;
                }
            }
            money = money + m + n;
            int p = m < n ? m / 2 : n / 2;
            m=0;
            n=0;
            for (int k = 1; k < N ; k++) {
                if (a[N - k] != 0 && a[N - k] <= p) {
                    a[N - k] = 0;
                }
            }
            for (int j = 0; j < N-1 ; j++) {
                if (a[j] != 0 ) {
                    remain++;
                }
            }
            if (remain==0||remain==1) break;
            else remain=0;

        }
        for (int j = 0; j < N ; j++) {
            if (a[j] != 0 ) {
                money += a[j];
            }
        }
        System.out.println(money);
    }
}

【代码的运行结果】

【代码的思想与解释说明】

输入N,创建数组并初始化数组,然后创建两个变量m,n用来存储最大的两个价格,并把最大的价格在数组里面标为0,意思是已经被购买了,然后得到优惠额度p,遍历数组,兑换额度内最贵的东西,然后把他的价格设置为0.

要注意兑换的东西不一定是第一个,最大值一定是后两位不是0的,但是两个最大值之间可能有0间隔,即经过一系列的兑换之后,数组就变成了稀疏数组,要注意对0进行筛选

最后跳出的有三种情况两个状态,假如有5件物品,进行一次买二赠一后再买二但是没有赠一了,此时数组内元素全部为0,跳出循环,假如有6件物品进行两次买二赠一之后数组为空,数组元素全为0,跳出.假如有7件物品进行两次买二赠一之后数组内只有一件商品,必须要单独买下,那么此时数组内元素只有一个非0元素,跳出循环单独买下此物品即可.

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不爱吃于先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值