目录
GitHub算法详细代码(多届比赛的多个算法题):yhbn/algorithm (github.com)https://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元素,跳出循环单独买下此物品即可.