Codeforces Round #610 (Div. 2)B

题意:你想要给朋友们买礼物 你现在有两种购买方法
第一种 花费a[i]的价格买一件物品
第二种 你现在有一种方法是选定k件物品然后 花费这k件物品中的最大值的价格 来得到这k件物品
你现在有p的钱数 问你最多能买到几件礼物
要想用少的钱数获得多的礼物数 那么我一定会用我的权利去获取k件物品
将物品价格排个序
dp【i】数组记录买i件物品花费的价钱
不使用权利正常买
dp[i] = dp[i-1] + a[i];
使用权利k个一起打包
dp[i] = dp[i-k] + a[i];
状态转移方程得到:
dp[i] = min(dp[i-1]+a[i],dp[i-k]+a[i]);
然后遍历之后 找出满足p钱可以买的最大的i是多少输出i即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
typedef long long ll;
const int MAXN = 2e5+7;
int a[MAXN],dp[MAXN];
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n,p,k;
        scanf("%d%d%d",&n,&p,&k);
        for(int i = 1;i <= n;i ++){
    
    
            scanf("%d",&a[i]);
        }
        sort(a+1,a+1+n);
        for(int i = 1;i <= n;i ++)
        {
    
    
            dp[i] = dp[i-1]+a[i];
            if(i >= k)
            {
    
    
                dp[i] = min(dp[i],dp[i-k]+a[i]);
            }
        }
        int ans = 0;
        for(int i = 1;i <= n;i ++)
        {
    
    
            if(p >= dp[i])
            {
    
    
                ans = max(ans,i);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45672411/article/details/104813730