B1+B2. K for the Price of One
题目链接-K for the Price of One (Easy Version)
题目链接-K for the Price of One (Hard Version)
题目大意
商店买东西,商店有n个物品,每个物品有自己的价格,商店有个优惠活动.
当你买恰好k个东西时可以只为其中最贵的那个付款,或者买一个东西单独付款
求有限的钱中买到的最多的物品数量(ps:你可以多次使用优惠)
解题思路
排序+DP
首先排序,如果我们买了第i件物品的话,那么第i - 1物品的价格应该小于这件物品,显然这样购买的顺序才最省钱
当物品小于k个的时候我们只有一种购买方法那就是一个个的买。当我们大于k的时候我们肯定选择连续买k个,我们用f[i]代表买前i件物品所需要的最小价钱
因为有两种购买方式,所以我们的状态转移方程为:
f[i]=min(f[i−k],f[i−1])+a[i])
如果得到的价钱f[i]<=p时,就可以更新答案
附上代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int INF=0x3f3f3f;
const int N=2e5+5;
int a[N],f[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--){
int n,p,k;
cin>>n>>p>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
int ans=0;
for(int i=1;i<=n;i++){
f[i]=f[i-1]+a[i];
if(i>=k)
f[i]=min(f[i],f[i-k]+a[i]);
if(f[i]<=p)
ans=max(ans,i);
}
cout<<ans<<endl;
}
return 0;
}