多重背包的讲解:
多重背包问题https://blog.csdn.net/yandaoqiusheng/article/details/84782655

1 for (int i = 1; i <= n; i++) {
2 int num = min(p[i], V / w[i]);
3 for (int k = 1; num > 0; k <<= 1) {
4 if (k > num) k = num;
5 num -= k;
6 for (int j = V; j >= w[i] * k; j--)
7 f[j] = max(f[j], f[j - w[i] * k] + v[i] * k);
8 }
9 }
本题题解:由于没有空间的限制,只是价值的限制,那么直接考虑用价值作为容量,然后状态定义为在所给物品可以拆分成价值为j的可能性,所有状态除了dp[0] = 0,其他等于-1
状态转移: dp[j] = max(dp[j] , dp[j-k*v[i]]]) k 用上面二分的方法
本题代码:
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 using namespace std;
5 int main()
6 {
7 int p[6];
8 int cnt = 0;
9 while(~scanf("%d%d%d%d%d%d",&p[0],&p[1],&p[2],&p[3],&p[4],&p[5])){
10 if(p[0]==0&&p[1]==0&&p[2]==0&&p[3]==0&&p[4]==0&&p[5]==0)
11 return 0;
12 int V = 0;
13 for(int i = 0; i < 6; i++){
14 V += p[i]*(i+1);
15 }
16 if(V%2!=0){
17 printf("Collection #%d:\n",++cnt);
18 printf("Can't be divided.\n");
19 puts("");
20 continue;
21 }
22 int dp[V/2+1];
23 memset(dp,-1,sizeof(dp));
24 dp[0] = 0;
25 for(int i = 0;i < 6; i++){
26 int num = p[i];
27 for(int k = 1; num>0 ; k<<=1){
28 if(k>num) k = num;
29 num -= k;
30 for(int j = V/2; j>=k*(i+1); j--){
31 dp[j] = max(dp[j],dp[j-k*(i+1)]);
32 }
33 }
34 }
35 /*for(int i = 0; i <= V/2; i++){
36 printf("%d ",dp[i]);
37 }
38 puts("");*/
39 if(dp[V/2]==0){
40 printf("Collection #%d:\n",++cnt);
41 printf("Can be divided.\n");
42 puts("");
43 }
44 else{
45 printf("Collection #%d:\n",++cnt);
46 printf("Can't be divided.\n");
47 puts("");
48 }
49 }
50 return 0;
51 }