POJ 1014 Dividing

题目见此:http://poj.grids.cn/practice/1014

解题思路:

  1. 如果做过几道多重背包的题的话,很明显可以看出是用多重背包,V = 总数/2, N = 6, n数组就是不同大小大理石的个数。
  2. 我们可以采用“输出方案数”的做法:在背包中用sum,初始化f[0] = 1, f[其余] = 0, 最后只要考察f[V]的值是不是0(方案数是不是0)即可。

贴代码:

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 #define sum(a, b) a+b
 5 const int MAXN = 7, MAXV = 20020*3;
 6 int f[MAXV], n[MAXN], N, V;
 7 
 8 void Pack_01(int cost, int weigh)
 9 {
10     for(int j=V ; j>=cost ; j--)
11         f[j] = sum(f[j], f[j-cost]);
12 }
13 void Pack_Com(int cost, int weigh)
14 {
15     for(int j=cost ; j<=V ; j++)
16         f[j] = sum(f[j], f[j-cost]);
17 }
18 void Pack_Mul(int cost, int weigh, int amount)
19 {
20     if(cost * amount >= V)
21     {    Pack_Com(cost, weigh);    return;}
22     for(int k=1 ; k<amount ; k=k<<1)
23     {
24         Pack_01(k*cost, k*weigh);
25         amount -= k;
26     }
27     Pack_01(amount*cost, amount*weigh);
28 }
29 
30 int main()
31 {
32     int Case = 1;
33     N = 6;
34     while(1)
35     {
36         V = 0;
37         for(int i=1 ; i<=6 ; i++)
38         {    cin >> n[i];    V += n[i] * c[i];}
39         if(V == 0)    break;
40         cout << "Collection #" << Case++ << ":" << endl;
41         if(V % 2 == 1)    {cout << "Can't be divided." << endl << endl;    continue;}
42         memset(f, 0, sizeof(f));
43         f[0] = 1;
44         V = V >> 1;
45         for(int i=1 ; i<=6 ; i++)
46             if(n[i])
47                 Pack_Mul(i, i, n[i]);
48         if(f[V])
49             cout << "Can be divided." << endl << endl;
50         else
51             cout << "Can't be divided." << endl << endl;
52     }
53 }
View Code

如果熟悉背包的话,这题比较简单,注意把背包写对就行了

由于这是多重背包,所以可以用单调队列优化,但写起来比较麻烦。这里留一个没有用单调队列的,pku1276和pku1742我写了单调队列优化的方法。

期末程设一定要考背包啊!!!枉费我学了好几个晚上……

posted on 2013-06-02 17:42  白~  阅读(112)  评论(0)    收藏  举报

导航