zoukankan      html  css  js  c++  java
  • abcd 多重背包

    这里写图片描述
    【数据规模与约定】
    对于 20%的数据,N≤10,-2≤a[i]< b[i]≤2;
    对于 60%的数据,N≤50, -20≤a[i]< b[i]≤20;
    对于 100%的数据,
    N≤200,-25≤a[i]< b[i]≤25,1≤c[i]≤20,0≤d[i] ≤10000
    ·
    ·
    ·
    ·
    解法:
    我一开始拿到这个题是很懵的。
    ·
    原来是一个背包!
    我们设A=Σe[i]*c[i],B=Σe[i]*d[i]。
    然后我们发现对于每一个 i ,我们e[i]每增加1,A就增加c[i],B就增加d[i]。背包?多重背包?

    因为e[i]=[a[i],b[i]]等价于[0,b[i]-a[i]]+a[i];,又因为∑e[i]*c[i]=0,∑b[i]*e[i],把这两个式子转换为,

    ∑(b[i]-a[i])*c[i]+∑a[i]*c[i]=0,∑(b[i]-a[i])*d[i]+∑a[i]*d[i]最大。

    第一个式子又变为∑(b[i]-a[i])*c[i]=-∑a[i]*c[i],所以背包体积是-∑a[i]*c[i],c
    是物品体积,d是物品价值。进行dp,二进制优化。

    这个背包必须装满:需要装满就要初始化f[0]=0,f[1~m]=-INF

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<cstring> 
    #define LL long long
    #define N 209
    using namespace std;
    int a[N],b[N],c[N],d[N],n;
    LL f[100009],v[100009],z[100009],p,Vm,Cm;
    void creat(int nn,int vv,int zz)
    {
        for(int i=1;i<=nn;i*=2)//二进制拆分成01背包 
        {
            v[++p]=i*vv;//体积 
            z[p]=i*zz;//价值 
            nn-=i; 
        }
        if(nn) v[++p]=nn*vv,z[p]=nn*zz;
    }
    int main()
    {
        memset(f,-127/3,sizeof(f));//初始化!
        f[0]=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
            Vm-=a[i]*c[i];Cm+=a[i]*d[i];b[i]-=a[i];
        }
        for(int i=1;i<=n;i++) creat(b[i],c[i],d[i]);
    
        for(int i=1;i<=p;i++)
         for(int j=Vm;j>=v[i];j--)
          f[j]=max(f[j],f[j-v[i]]+z[i]);
        printf("%lld",f[Vm]+Cm);
        return 0;
    }
  • 相关阅读:
    “Metro”,移动设备视觉语言的新新人类
    三个排序
    window.location.reload;刷新
    2012年7月4日
    PDO基础(一)
    php数组
    smarty(原理概述)
    php函数
    jquery Poshy Tip
    WAMP:PHP基础(一)
  • 原文地址:https://www.cnblogs.com/dfsac/p/7587802.html
Copyright © 2011-2022 走看看