B4104 [CSP-X2024 山东] 购物
题目描述
双十一,很多人在疯狂地购物。
商家推出了各种各样的优惠活动,吸引顾客购买更多的商品。
某商家推出如下的优惠活动:
该商家共有 n n n 件商品,单独购买第 i i i 件商品的费用为 a i a_i ai。顾客也可以花费 w w w 购买 一张优惠券,一张优惠券最多可兑换 m m m 件商品(无需额外付费)。顾客可以购买任意张优惠券;
如果最后商品不足 m m m 件,优惠券也可以使用。
求顾客购买完所有 n n n 件商品的最小费用。
输入格式
第一行有 3 3 3 个整数 n , m , w n, m, w n,m,w。
第二行有 n n n 个整数,第 i i i 个为 a i a_i ai,表示第 i i i 件商品的费用。
输出格式
购买所有商品的最小费用。
输入输出样例 #1
输入 #1
5 2 8
2 7 1 8 4
输出 #1
15
输入输出样例 #2
输入 #2
5 3 8
6 7 4 8 9
输出 #2
16
说明/提示
样例解释
样例 1 1 1 说明:
花费 8 8 8 买一张优惠券,兑换第 2 2 2、第 4 4 4 件商品;第 1 1 1、第 3 3 3、第 5 5 5 件商品直接购买。
共花费 8 + 2 + 1 + 4 = 15 8 + 2 + 1 + 4 = 15 8+2+1+4=15。
样例 2 2 2 说明:
花费 16 16 16 购买两张优惠券,能兑换所有商品。
数据范围
对于 30 % 30\% 30% 的数据,满足 1 ≤ n ≤ 1 0 3 , 1 ≤ m ≤ 1 0 3 , 1 ≤ w ≤ 1 0 9 , 1 ≤ a i ≤ 1 0 9 1 \leq n \leq 10^3,1 \leq m \leq 10^3,1 \leq w \leq 10^9,1 \leq a_i \leq 10^9 1≤n≤103,1≤m≤103,1≤w≤109,1≤ai≤109。
对于 100 % 100\% 100% 的数据,满足 1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ m ≤ 2 × 1 0 5 , 1 ≤ w ≤ 1 0 9 , 1 ≤ a i ≤ 1 0 9 1 \leq n \leq 2 \times 10^5,1 \leq m \leq 2 \times 10^5,1 \leq w \leq 10^9,1 \leq a_i \leq 10^9 1≤n≤2×105,1≤m≤2×105,1≤w≤109,1≤ai≤109。
【题目解析】
由于可以花费w获得一张优惠券,来直接获取m件商品,基于最小消费的原则,我们应当把这张优惠券用在最贵的几件商品上,所以,可以对原序列进行排序,然后按照从大到小的原则,每m件商品计算出其总价s,与w比较,如果比w大,那么需要购买一张优惠券,花费w,否则,不需要购买优惠券,花费s。
需要考虑如果商品数量不够m,但是价格也超过 w的情况,这时我们也可以使用优惠券。
【代码展示】
#include<bits/stdc++.h>
using namespace std;
long long n,m,w,s=0,k=0,s1=0;
const int N=2e5+10;
int a[N];
int main(){
cin>>n>>m>>w;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1);
for(int i=n;i>=1;i--){
s=s+a[i];//累加m件商品的总价
k++;//商品数量+1
if(k==m){//每m件商品做一次处理
if(s>w){//如果m件商品总价太高,那么用优惠券
s1=s1+w;
s=0;
}
else{//如果m件商品总价比较少,那么不用优惠券
s1=s1+s;
s=0;
}
k=0;
}
}
//考虑最后不够m件商品的情况
if(s>w) s1=s1+w;
else s1=s1+s;
cout<<s1;
return 0;
}