codeforces 1282B2. K for the Price of One (Hard Version) (dp)

链接 https://codeforces.com/contest/1282/problem/B2

题意: 商店买东西,商店有n个物品,每个物品有自己的价格,商店有个优惠活动,当你买恰好k个东西时可以只为其中最贵的那个付款,求有限的钱中买到的最多的物品数量,你可以多次使用优惠。

思路:把所有商品的价格排序从小到大一遍,设第i个物品的价格是a[i],Sum[i]表示购买前i个物品花费的钱,作为前缀和。可以发现当你买了当第i个物品时,那么只需要支付Sum[i-k] + a [i] 即可,因为你买了当前的物品,可以赠送k-1个,那直接贪心着把小于等于当前这个物品价格的前K-1个物品直接赠送了,只需要支付a[i]费用,再支付一下sum[i-k]即可,维护整个过程sum[i] = sum[i-k] + a[i]即可。

AC代码:

 1 #include<iostream>
 2 #include<string>
 3 #include<vector>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 using namespace std;
 8 typedef long long ll;
 9 ll mod = 1e9+7;
10 const int maxn = 2e5+10;
11 int main(){
12     int q;cin>>q;
13     while(q--){
14         ll n,p,k;cin>>n>>p>>k;
15         ll a[maxn];
16         a[0] = 0;
17         for(int i = 1;i<=n;i++) cin>>a[i];
18         sort(a+1,a+n+1);
19         ll ans = 0;
20         // 2 3 4 5 7 
21         ll sum[n+1];
22         memset(sum,0,sizeof(sum));
23         sum[0] = 0;
24         sum[1] = a[1];
25         for(int i = 2;i<=k;i++){
26             sum[i] = sum[i-1] + a[i];//前k个物品价格必须都要算上,此时没有优惠卷
27         }
28         for(int i = k;i<=n;i++){
29             sum[i] = sum[i-k] + a[i];
30         }
31         for(int i = 0;i<=n;i++){
32             if(p>=sum[i]) ans = i ;
33         }
34         cout<<ans<<endl;
35     }
36     return 0;
37 }
posted @ 2020-01-01 21:32  AaronChang  阅读(483)  评论(0编辑  收藏  举报