标签:
http://soj.sysu.edu.cn/show_problem.php?pid=1001&cid=1769
其实感觉多重背包比01背包和完全背包都要难,每件物品的数量可能不止一件,还是求放入背包的物品的最大价值。
在背包九讲中,给出的动态转移方程为:
f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}
但是感觉还是考虑边界问题比较烦人,所以我想的是把多重背包和之前的01背包联系起来......不知道行不行
这里我写了一种一维dp数组的写法,在这题测试是tle的,因为这题的数据量太大,怎么解决后面再说......
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 int a[10]; 8 int w[10]={3, 5, 2, 6, 11, 8}; 9 double v[10]={0.01, 0.05, 0.10, 0.25, 0.50, 1}; 10 double dp[10005]; 11 //double dp[15][10005]; 12 13 int main() 14 { 15 int m; 16 while(scanf("%d", &m) != EOF) 17 { 18 memset(dp, 0, sizeof(dp)); 19 int n=6; 20 for(int i=0; i<n; i++) 21 scanf("%d", &a[i]); 22 //一维 23 for(int i=0; i<n; i++) 24 for(int j=0; j<a[i]; j++) //相当于把物品分成一件一件 25 for(int k=m; k>=w[i]; k--) 26 dp[k] = max(dp[k-w[i]]+v[i], dp[k]); 27 //二维 28 /* 29 for(int i=1; i<=n; i++) 30 for(int j=0; j<=m; j++) 31 for(int k=0; k<=a[i]; k++) 32 { 33 if(j >= k*w[i]) 34 dp[i][j] = max(dp[i-1][j-k*w[i]]+k*v[i], dp[i][j]); 35 } 36 */ 37 printf("$%.2lf\n", dp[m]); 38 //printf("$%.2lf\n", dp[n][m]); 39 } 40 return 0; 41 }
看注释那一行就相当于把相同的这几件物品分成一件件,然后套用01背包的方法来解决!
那要怎么解决超时问题呢?
用到了二进制划分的办法,分成1,2,4,8,16...64.....(剩下的)
假如物品有12件,就分成1,2,4,5(这里的5就是剩下的),这样,如果我想拿7件,就用1+2+4来凑就好了,只用遍历3次,而不是7次!省了好多时间!
最后还是用01背包解决!
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 int a[15]; 8 double dp[15000]; 9 int weight[15]={3, 5, 2, 6, 11, 8}; 10 double value[15]={0.01, 0.05, 0.10, 0.25, 0.50, 1}; 11 int w[15000]; 12 double v[15000]; 13 14 int main() 15 { 16 int N=6; 17 int m; 18 while(scanf("%d", &m) != EOF) 19 { 20 memset(dp, 0, sizeof(dp)); 21 int count = 0; 22 for(int i=0; i<N; i++) 23 scanf("%d", &a[i]); 24 25 for(int i = 0; i < N; ++i) 26 { 27 for(int j = 1; j <= a[i]; j <<= 1) // 二进制拆分 28 { 29 w[count] = j * weight[i]; 30 v[count++] = j * value[i]; 31 a[i] -= j; 32 } 33 if(a[i] > 0) 34 { 35 w[count] = a[i] * weight[i]; 36 v[count++] = a[i] * value[i]; 37 } 38 } 39 for(int i = 0; i < count; ++i) // 使用01背包 40 for(int j = m; j >= w[i]; j--) 41 dp[j] = max(dp[j-w[i]]+v[i], dp[j]); 42 printf("$%.2lf\n",dp[m]); 43 } 44 return 0; 45 }
标签:
原文地址:http://www.cnblogs.com/dominjune/p/4409220.html