多重背包问题,一般有三种思路优化: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 }