POJ-2754 Similarity of necklaces 2 多重背包

  题目链接: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 }

 

你可能感兴趣的:(poj)