【题目分析】
首先,这个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 */