题目链接:http://poj.org/problem?id=2754
当时居然没有想到是多重背包,敲了个分组背包,TLE。。。
后来才知道可以转化为多重背包,即把每个下界L[i]放为0,上限为U[i]-L[i],就是物品的个数,价值为P[i],花费为M[i]。本来题目要求Σ(M[i]*Table[i])=0时,Σ(P[i]*Table[i])的最大值。现在Table[i]的每个值都加了-L[i],即Σ(M[i]*Table[i] + M[i]*L[i]) 时,Σ(P[i]*Table[i] + P[i]*L[i])的最值,由Σ(M[i]*Table[i])=0可知,背包的容量为Σ(M[i]*L[i]),典型的多重背包问题了。最后再把累加的值减去就行了。
1 //STATUS:C++_AC_375MS_580KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 using namespace std; 13 #define LL __int64 14 #define pii pair<int,int> 15 #define Max(a,b) ((a)>(b)?(a):(b)) 16 #define Min(a,b) ((a)<(b)?(a):(b)) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 const int N=210,INF=0x3f3f3f3f,MOD=100000000; 21 const double DNF=100000000000; 22 23 int f[N*25*20],pa[N],m[N],l[N],up[N]; 24 int n,rp,rm; 25 26 void zo(int v,int w) 27 { 28 int j; 29 for(j=rm;j>=v;j--){ 30 if(f[j-v]>=0) 31 f[j]=Max(f[j],f[j-v]+w); 32 } 33 } 34 35 int main() 36 { 37 // freopen("in.txt","r",stdin); 38 int i,j,k; 39 while(~scanf("%d",&n)) 40 { 41 mem(f,-1); 42 for(i=rm=rp=0;i<n;i++){ 43 scanf("%d%d%d%d",&pa[i],&m[i],&l[i],&up[i]); 44 rp+=l[i]*pa[i]; 45 rm-=l[i]*m[i]; 46 up[i]-=l[i]; 47 } 48 f[0]=0; 49 for(i=0;i<n;i++){ 50 for(k=1;up[i]>k;up[i]-=k,k<<=1){ 51 zo(k*m[i],k*pa[i]); 52 } 53 if(up[i])zo(up[i]*m[i],up[i]*pa[i]); 54 } 55 56 printf("%d\n",f[rm]+rp); 57 } 58 return 0; 59 }