多重背包的讲解:
多重背包问题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: ",++cnt); 18 printf("Can't be divided. "); 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: ",++cnt); 41 printf("Can be divided. "); 42 puts(""); 43 } 44 else{ 45 printf("Collection #%d: ",++cnt); 46 printf("Can't be divided. "); 47 puts(""); 48 } 49 } 50 return 0; 51 }