1. 程式人生 > >51nod1086 背包問題 V2——二進制優化

51nod1086 背包問題 V2——二進制優化

view 中間 const size har clu names lang color

有N種物品,每種物品的數量為C1,C2......Cn。從中任選若幹件放在容量為W的背包裏,每種物品的體積為W1,W2......Wn(Wi為整數),與之相對應的價值為P1,P2......Pn(Pi為整數)。求背包能夠容納的最大價值。 Input
第1行,2個整數,N和W中間用空格隔開。N為物品的種類,W為背包的容量。(1 <= N <= 100,1 <= W <= 50000)
第2 - N + 1行,每行3個整數,Wi,Pi和Ci分別是物品體積、價值和數量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)
Output
輸出可以容納的最大價值。
Input示例 3 6 2 2 5 3 3 8 1 4 1 Output示例 9 這就是裸的二進制優化dp 方法是: 將第i種物品分成若幹件物品,其中每件物品有一個系數,這件物品的費用和價值均是原來的費用和價值乘以這個系數。 使這些系數分別為 1,2,4,...,2^(k-1),n[i]-2^k+1,且k是滿足n[i]-2^k+1>0的最大整數。 例如,如果n[i]為13,就將這種物品分成系數分別為1,2,4,6的四件物品。
這樣就能在log的復雜度下求出所有搭配方法的答案辣 技術分享
#include<cstdio>
#include<cstring>
#include
<algorithm> using namespace std; const int M=107; int read(){ int ans=0,f=1,c=getchar(); while(c<0||c>9){if(c==-) f=-1; c=getchar();} while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();} return ans*f; } int n,m; int c[M],w[M],h[M],f[50007]; int main() { n
=read(); m=read(); for(int i=1;i<=n;i++) c[i]=read(),w[i]=read(),h[i]=read(); for(int i=1;i<=n;i++){ int now=h[i],j=1; while(j<now){ for(int k=m;k>=c[i]*j;k--) f[k]=max(f[k],f[k-c[i]*j]+w[i]*j); now-=j; j*=2; } for(int k=m;k>=c[i]*now;k--) f[k]=max(f[k],f[k-c[i]*now]+w[i]*now); for(int i=0;i<=m;i++) printf("[%d] ",f[i]);printf("\n"); } printf("%d\n",f[m]); return 0; }
View Code

51nod1086 背包問題 V2——二進制優化