红字差评系列3.abcd

【题目分析】

   首先,这个e[i]是在a[i]~b[i]的,而且要{c[i]*e[i]}为0,{d[i]*e[i]}最大。

  我们把a[i]~b[i]这个区间向左平移a[i]个单位,于是这个区间就变成了0~b[i]-a[i],假设b1[i]=b[i]-a[i],此时的e1[i]=e[i]-a[i](也就是比原来的数字小了a[i])(这里为了区分,都把平移后的数组用1标记一下QAQ)。

  这样问题就变成了一个多重背包的问题。有n中物品,每一种物品有e1[i](0~b1[i])个,c[i]为该种物品的体积,d[i]为该种物品的价值,背包的总容量为-{c[i]*a[i]}(因为∑c[i]*e[i]=0,e1[i]=e[i]-a[i],所以有∑c[i]*(e1[i]+a[i])=0——> ∑c[i]*e1[i]+∑c[i]*a[i]=0——>∑c[i]*e1[i]=-∑c[i]*a[i])。要求最大的背包价值∑d[i]*e[i]也就是∑d[i]*e1[i]+∑d[i]+a[i]。

  然后这个∑c[i]*a[i]是可以在读入时候处理出来的,前面-∑c[i]*a[i]也一样。

  就...没了。

  歇歇峰峰的。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=100010;
int n,m,a[maxn],b[maxn],c[maxn],d[maxn];
int tiji[maxn],jiazhi[maxn],ans,num;
int f[maxn];
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')if(ch=='-')f=-1,ch=getchar();
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
void Pre(int tj,int jz,int gs)
{
    for(int i=1;i<=gs;i*=2)
        gs-=i,tiji[++num]=tj*i,jiazhi[num]=jz*i;
    if(gs) tiji[++num]=gs*tj,jiazhi[num]=jz*gs;
}
int main()
{
    freopen("abcd.in","r",stdin);
    freopen("abcd.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();b[i]=read();
        c[i]=read();d[i]=read();
        b[i]-=a[i];
        m-=c[i]*a[i];
        ans+=a[i]*d[i];
    }
    for(int i=1;i<=n;i++)
        Pre(c[i],d[i],b[i]);
    memset(f,-0x3f,sizeof f);
    f[0]=0;
    for(int i=1;i<=num;i++)
        for(int j=m;j>=tiji[i];j--)
            f[j]=max(f[j],f[j-tiji[i]]+jiazhi[i]);
    cout<<ans+f[m];
    return 0;
}

/*
10
1 10 1 0
-10 10 2 2
-10 10 2 2
-10 10 2 2
1 10 1 0
-10 10 2 2
-10 10 2 2
1 10 1 0
-10 10 2 2
1 10 1 0 
*/

 

posted @ 2016-11-10 19:22  [lemon]  阅读(243)  评论(4编辑  收藏  举报
……