设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其质量 ≤ 100g),求出用它们能称出的质量的种类数(不包括质量为0的情况)。
动态规划
设dp[100]数组为标记数组。当dp[i] = 0时, 表示质量为i的情况,目前没有被称出;当dp[i] = 1时,表示质量为i的情况已经称出。
当处理第j个砝码时, 其质量为w[j],有
if(dp[i - w[j]] == 1)
dp[i] = 1;
int weight[]; //不同种类砝码的重量
int nums[]; //不同种类砝码对应的数量
int total = 0; //当前可能称出的最大值;
//选取第j种类的砝码
for(int j = 0; j < len; ++j)
{
total += weight[j] * nums[j];
for(int i = weight[j]; i <= total; ++i)
{
if(dp[i - weight[j]])
dp[i] = 1;
}
}
int cnt = 0; //可能的称重
for(int k = 1; k <= total; ++k)
{
if(dp[k])
++cnt;
}
母函数方法
设输入质量为w的砝码n个,则可以用母函数表示为:定义x(i)为x的i次方,
f(w, n) = 1 + x(1) + x(2) +… + x(n);
针对给定的例子,若输入的砝码(1g、2g、3g、5g、10g、20g)的个数分别为1、2、2、0、0、1,则有:
f1(1,1) = 1 + x(1);
f2(2, 2) = 1 + x(2) + x(4);
f3(3, 2) = 1 + x(3) + x(6);
f4(20, 1) = 1 + x(20);
F = f1(1, 1) * f2(2, 2) * f3(3, 2) * f4(20, 1)
= 1 + x(1) + x(2) + x(3) + x(4) + x(5) + x(6) + x(7) + x(8) + x(9) + x(10) + x(11) + x(20)
+ x(21) + x(22) + x(23) + x(24) + x(25) + x(26) + x(27) + x(28) + x(29) + x(30) + x(31)