Codeforces Round #610 (Div. 2)B1+B2 K for the Price of One

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;
}
发布了23 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Fiveneves/article/details/104129726
今日推荐