51nod1086(多重背包&二進制)
題目鏈接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1086
題意:中文題誒~
思路:很顯然這是一道多重背包題,不過這裏的數據有點大,如果將物品一個一個地拆分爲開再用01背包做的話時間復雜度
爲O(n*w*ci)=200*5000*200=2e9,顯然是會超時的;
那麼不妨往二進制方向想一想,任何數都可以寫成:2^a1+2^a2+2^a3......
反之則有對於任意數 ci,0~ci的所有數都可以由 2^0, 2^1, 2^2.....2^m 中的羅幹個組合成,其中m爲ci的二進制長度...
那麼可以將ci分解成上述形式,再枚舉一下01背包即可...
代碼:
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 const int MAXN=200+10; 6 int w[MAXN], v[MAXN], dp[(int)1e5+10]; 7 8 int main(void){ 9 int n, m; 10 scanf("%d%d", &n, &m); 11 for(int i=1; i<=n; i++){ 12 int a, b, c; 13 scanf("%d%d%d", &a, &b, &c); 14 int cnt=1; 15 while(cnt<=c){ 16 for(int j=m; j>=a*cnt; j--){ 17 dp[j]=max(dp[j], dp[j-a*cnt]+b*cnt); 18 } 19 c-=cnt; 20 cnt<<=1; 21 } 22 if(c){ 23 for(int j=m; j>=c*a; j--) 24 dp[j]=max(dp[j], dp[j-c*a]+c*b); 25 } 26 } 27 printf("%d\n", dp[m]); 28 return 0; 29 }
我就是我,颜色不一样的烟火 --- geloutingyu