题目地址:http://poj.org/problem?id=1276
1 /* 2 有n件物品和一个容量为v的背包,第i种物品最多有n[i]件可用, 3 每件费用是c[i],价值是w[i],求解将哪些物品放入背包 4 使费用总和不超过背包容量且价值总和最大 5 6 for(i=1; i<=n; ++i) 7 for(j=0; j<=v; ++j) 8 for(k=0; k*c[i]<=j; ++k) 9 dp[i][j] = max(dp[i][j],dp[i-1][j-k*c[i]]+k*w[i]); 10 时间复杂度为O(V*∑n[i]); 11 另一种思想是二进制优化,时间复杂度为O(V*∑log(n[i])); 12 详见图片 13 */ 14 #include <stdio.h> 15 #include <string.h> 16 int cash; 17 int n[11],dk[11]; 18 int dp[1000000]; 19 inline int max(const int &a, const int &b) 20 { 21 return a < b ? b : a; 22 } 23 void CompletePack(int cost) 24 { 25 for(int i=cost; i<=cash; ++i) 26 dp[i] = max(dp[i],dp[i-cost]+cost); 27 } 28 void ZeroOnePack(int cost) 29 { 30 for(int i=cash; i>=cost; --i) 31 dp[i] = max(dp[i],dp[i-cost]+cost); 32 } 33 void MultiplePack(int cnt, int cost) 34 { 35 if(cnt*cost >=cash)//如果第i种物品的费用总和超过背包容量,那么就是完全背包问题 36 CompletePack(cost); 37 else 38 { 39 int k = 1;//二进制拆分 40 while(k<cnt) 41 { 42 ZeroOnePack(cost*k); 43 cnt -=k; 44 k<<=1; 45 } 46 ZeroOnePack(cnt*cost); 47 } 48 } 49 int main() 50 { 51 int N,i,k,cnt,j; 52 while(scanf("%d%d",&cash,&N)!=EOF) 53 { 54 memset(dp,0,sizeof(dp)); 55 for(i=1; i<=N; ++i) 56 scanf("%d%d",&n[i],&dk[i]); 57 for(i=1; i<=N; ++i) 58 { 59 MultiplePack(n[i],dk[i]); 60 } 61 printf("%d\n",dp[cash]); 62 } 63 return 0; 64 }
时间: 2024-11-02 17:46:24