POJ 1276 完全背包
---恢复内容开始---
这道题就是明显的完全背包题啦,只不过物品的重量和价值是一样的。
我就是按照《背包九讲》中完全背包的思路,先把物品的数量 ni 按照1,2,4,8...的规律分解,然后直接用简单背包暴力
数据比较小,10种物品,每一种最多1000个,cash<=100000,这样子复杂度就是 10*log(1000)*100000,10的7次方刚好能过
下面是我的代码
1 #include<stdio.h> 2 #include<iostream> 3 using namespace std; 4 5 #include<math.h> 6 #include<algorithm> 7 #include<string.h> 8 #include<stdlib.h> 9 #include<vector> 10 #include<set> 11 #include<map> 12 #include<stack> 13 #include<string> 14 #include<queue> 15 16 #define repA(p,q,i) for( int (i)=(p); (i)!=(q); ++(i) ) 17 #define repAE(p,q,i) for( int (i)=(p); (i)<=(q); ++(i) ) 18 #define repD(p,q,i) for( int (i)=(p); (i)!=(q); --(i) ) 19 #define repDE(p,q,i) for( int (i)=(p); (i)>=(q); --(i) ) 20 21 22 int dismiss[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048}; 23 int ni[20], di[20]; 24 int ci[110]; 25 int dp[100010]; 26 27 int main() 28 { 29 int cash, n; 30 while( scanf("%d%d", &cash, &n) != EOF ) 31 { 32 repA(0, n, i) 33 scanf("%d%d", &ni[i], &di[i]); 34 35 int rd=0; 36 repA(0, n, i) 37 { 38 int tmp = ni[i] + 1; 39 int dt; 40 for(dt = 1; dt < 11; ++dt) 41 { 42 if(tmp >= dismiss[dt]) 43 ci[rd++] = dismiss[dt-1] * di[i]; 44 else break; 45 } 46 --dt; 47 ci[rd++] = (ni[i] + 1 - dismiss[dt]) * di[i] ; 48 } 49 50 memset(dp, 0, sizeof(dp) ); 51 52 repA(0, rd, i) 53 repDE(cash, ci[i], j) 54 dp[j] = max(dp[j], dp[j-ci[i] ] + ci[i] ); 55 56 printf("%d\n", dp[cash]); 57 58 59 } 60 return 0; 61 }
网上还有个大牛的代码比完全背包有了一个数量级的优化,貌似有点复杂,不过还是推荐去膜拜啊~~~
链接:http://blog.csdn.net/lyy289065406/article/details/6648102
To Be The Best Of Yourself