zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    (原)Lazarus 异构平台下多层架构思路、DataSet转换核心代码
    (学)新版动态表单研发,阶段成果3
    (学) 如何将 Oracle 序列 重置 清零 How to reset an Oracle sequence
    (学)XtraReport WebService Print 报错
    (原)三星 i6410 刷机 短信 无法 保存 解决 办法
    (原) Devexpress 汉化包 制作工具、测试程序
    linux下网络配置
    apache自带ab.exe小工具使用小结
    Yii::app()用法小结
    PDO使用小结
  • 原文地址:https://www.cnblogs.com/valk3/p/12807216.html
Copyright © 2011-2022 走看看