多重背包问题,一般有三种思路优化:1.用2^n拆分数量,转化为01背包。2.当成完全背包来做,需要用一个数组记录每个物品的数量,当使用次数超过时结束。3.用单调队列优化(目前还不懂的说)。上次做男人八题里的coin时我用的是第二种思路,这次我用的是第一种。
1 #include <stdio.h> 2 #include <string.h> 3 bool dp[60006]; 4 int a[10],b[100]; 5 int cnt,sum; 6 bool read() 7 { 8 int i; 9 bool f = 0; 10 sum = 0; 11 for(i = 1; i <= 6; i++) 12 { 13 scanf("%d",&a[i]); 14 if(a[i]) f = 1; 15 sum += a[i]*i; 16 } 17 return f; 18 } 19 void inst(int n) 20 { 21 for(int i = 0; a[n] >= (1<<i); i++) 22 { 23 b[cnt++] = (1<<i)*n; 24 a[n] -= (1<<i); 25 } 26 if(a[n]) b[cnt++] = a[n]*n; 27 } 28 int main() 29 { 30 int i,j,cas=1; 31 bool ok; 32 while(read()) 33 { 34 printf("Collection #%d:\nCan",cas++); 35 if(sum & 1) 36 { 37 printf("'t be divided.\n\n"); 38 continue; 39 } 40 cnt = 0; 41 for(i = 1; i <= 6; i++) 42 inst(i); 43 sum /= 2; ok = 0; 44 memset(dp,0,sizeof dp); 45 dp[0] = 1; 46 for(i = cnt-1; i >= 0; i--) 47 { 48 if(dp[sum]) 49 {ok = 1; break;} 50 if(b[i] > sum) break; 51 for(j = sum; j >= b[i]; j--) 52 if(dp[ j-b[i] ]) 53 dp[j] = 1; 54 } 55 if(!ok) printf("'t"); 56 printf(" be divided.\n\n"); 57 } 58 return 0; 59 }