• CF#214 C. Dima and Salad 01背包变形


    C. Dima and Salad

    题意

    有n种水果,第i个水果有一个美味度ai和能量值bi,现在要选择部分水果做沙拉,假如此时选择了m个水果,要保证(frac{sum_{i=1}^ma_i}{sum_{i=1}^mb_i}==k),问沙拉最大的美味度是多少?

    思路

    01背包变形。

    对于给出的公式,我们化简一下:
    (sum_{i=1}^ma_i-k*sum_{i=1}^mb_i==0)
    就变成了把a[i]-k*b[i]作为体积,a[i]作为价值,向容量为0的背包里放,可以取得的最大价值。

    因为a[i]-k*b[i]有正负,所以我们可以分别对正体积和负体积DP,体积为0直接算到答案中,在正负的DP值之中选择体积绝对值相等的最大和。

    代码

    //#include<bits/stdc++.h>
    #include<vector>
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #include<string>
    #include<math.h>
    #include<queue>
    #include<map>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int N=1e5+10;
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
     
    struct note
    {
        int a,b;
        int wei;
    } arr[N];
    int dp1[N],dp2[N];
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++)
            scanf("%d",&arr[i].a);
        int spos=0,sneg=0,ans=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&arr[i].b);
            int tmp=arr[i].a-k*arr[i].b;
            arr[i].wei=tmp;
            if(tmp>0)
                spos+=tmp;//正体积的和
            else if(tmp<0)
                sneg-=tmp;//负体积的和
            else
                ans+=arr[i].a;//体积为0直接算贡献
        }
        memset(dp1,0x8f,sizeof(dp1));
        memset(dp2,0x8f,sizeof(dp2));
        dp1[0]=dp2[0]=0;
        for(int i=1; i<=n; i++)//正
        {
            if(arr[i].wei<=0)
                continue;
            for(int j=spos; j>=arr[i].wei; j--)
                dp1[j]=max(dp1[j],dp1[j-arr[i].wei]+arr[i].a);
        }
        for(int i=1; i<=n; i++)//负
        {
            if(arr[i].wei>=0)
                continue;
            for(int j=sneg; j>=-arr[i].wei; j--)
                dp2[j]=max(dp2[j],dp2[j+arr[i].wei]+arr[i].a);
        }
        int rel=0;
        for(int i=1; i<=min(sneg,spos); i++)//选择两个体积绝对值相等的最大值
        {
            if(dp1[i]>0&&dp2[i]>0)
                rel=max(rel,dp1[i]+dp2[i]);
        }
        ans+=rel;
        if(ans==0)
            printf("-1
    ");
        else
            printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    laravel底层源码解析:pipeline,db,console
    composer命令清单
    composer使用笔记
    git常见问题
    JS阻止冒泡和取消默认事件(默认行为)
    vue项目构建:vue-cli+webpack常用配置
    MVC和三层架构
    SSM框架初始配置
    Java对象间的关系
    Spring框架
  • 原文地址:https://www.cnblogs.com/valk3/p/12807216.html
Copyright © 2020-2023  润新知