http://linjianxionggo.blog.163.com/blog/static/8532250020107310235772/
例如右端有2x5 项,即称出5克的方案有2:5=3+2=4+1,同样,6=1+2+3=4+2;10=1+2+3+4。故称出6克的方案有2,称出10克的方案有1 .
例二、若有1元、5元、10元、20元、50元的人民币一堆,能凑出100元有几种可能方案?
如何解决这个问题呢?考虑构造母函数。
类似于非完全背包问题,
如cost[5] = {1, 5, 10, 20, 50}
num[5] = {50, 61, 23, 21, 11}
背包大小为100.
母函数构造如下:
(1+x1+x2+x3+.....+x50)*(1+x5+x10+x15+...+x305)*(1+x10+x20+...+x230)*(1+x20+x40+x60+....+x420)*(1+x50+x100+...+x550)
求最后x100的系数,即为所求。
前i个数的选择
f[i][v] = SUM( f[i-1][ v-k*cost[i]] ) (0<=k<=num[i] && v-k*cost[i]>=0)
代码如下:
cost[]={1,5,10,20,50,100}; num[]={50,61,...}; pack[101] ={0}; pack[0] =1; for(int i = 0; i<cost.length; i++) for(int j=100; j>=1; j--) //必须逆序 { if(pack[j] != 0) { k=0; while(k<=num[i] && j+k*cost[i] <=100) { a[j+k*b[i]] += a[j]; k++; } } } cout<<a[100]<<endl; ////////////////////////// another method f[0]=1; //init for(int i=0; i<cost.length; i++) for(int v=100; v>=0; v++) { int times = num[i]; for(int k=v; k>=0 && times-->=0; k-=cost[i]) { if(pack[k]==0) continue; pack[v] += pack[k]; } } cout<<pack[100]<<endl;