八.背包问题方案总数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了八.背包问题方案总数相关的知识,希望对你有一定的参考价值。

.背包问题方案总数
        对于一个给定了背包容量、物品费用、物品间相互关系(分组、依赖等)的背包问题,除了再给定每个物品的价值后求可得到的最大价值外,还可以得到装满背包或将背包装至某一指定容量的方案总数。
  对于这类改变问法的问题,一般只需将状态转移方程中的max改成sum即可。例如若每件物品均是01背包中的物品,转移方程即为f[i][v]=sum{f[i-1][v],f[i-1][v-w[i]]+c[i]},初始条件f[0][0]=1。
  事实上,这样做可行的原因在于状态转移方程已经考察了所有可能的背包组成方案。
货币系统
【问题描述】
  给你一个n种面值的货币系统,求组成面值为m的货币有多少种方案。样例:设n=3,m=10,要求输入和输出的格式如下:
【样例输入】money.in
3  10                                //3种面值组成面值为10的方案
1                                      //面值1
2                                      //面值2
5                                      //面值5
【样例输出】money.out
  10                             //有10种方案
 
 
算法
设f[j]表示面值为j的最大方案数, 如果f[j-k*a[i]]!=0则f[j]=f[j]+f[j-k*a[i]],
当1<=i<=n,m>=j>= a[i],1<=k<=j / a[i]。 #include<cstdio> int m, n; int a[1001]; long long f[10001]; int main() { scanf("%d%d",&n,&m); for (int i = 1; i <= n; i++) scanf("%d",&a[i]); f[0] = 1; for (int i = 1; i <= n; i++) for (int j = m; j >= a[i]; j--) for (int k = 1; k <= j / a[i]; k++) f[j] += f[j-k*a[i]]; printf("%lld",f[m]); return 0; }

 

 
【算法分析2】
  设f[j]表示面值为j的总方案数,如果f[j-a[i]]!=0则f[j]=f[j]+f[j-a[i]],1<=i<=n,a[i]<=j<=m。
【参考程序2】
#include<cstdio>
using namespace std;

int n, m;
int a[101];
long long f[10001];            

int main(){
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= n; i++)
       scanf("%d",&a[i]);
    f[0] = 1;
    for (int i = 1; i <= n; i++)
       for (int j = a[i]; j <= m; j++)
          f[j] += f[j-a[i]];
    printf("%lld",f[m]);
    return 0;
}

 

以上是关于八.背包问题方案总数的主要内容,如果未能解决你的问题,请参考以下文章

poj 2229 Sumsets 完全背包求方案总数

518-零钱兑换 II(完全背包-求方案总数)

完全背包p1832A+B Problem(再升级)

动态规划(Dynamic Programming)

背包方案

背包DP 方案数---P1832 A+B Problem(再升级)