背包问题的方案总数例题:货币系统

版权声明:个人笔记,仅供复习 https://blog.csdn.net/weixin_41162823/article/details/88055874

【例9-17】货币系统

【问题描述】

  给你一个n种面值的货币系统,求组成面值为m的货币有多少种方案。样例:设n=3,m=10,要求输入和输出的格式如下:

【样例输入】

3  10                          

1                                     

2                                  

5                                   

【样例输出】

10                         

 

解题思路:本题是一个求完全背包的方案总数的问题,我们假设f[ v ] 存放背包体积为 v 时的方案总数,那么很显然状态转移方程就从原来的求最大值变成了求和,能这样写的原因在于状态转移方程已经考察了所有可能的背包组成方案。

代码示例:设f[j]表示面值为j的最大方案数, 如果 f[j - k*val[i] ] != 0则f[j] = f[ j ] + f[ j - k*a[i] ],当1 <= i <= n,m >= j >= val[ i ],1 <= k <= j / val[ i ]。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int n,m;
const int maxn = 1100;
int val[maxn];
ll f[maxn*10];
void solve(){
	memset(f,0,sizeof f);
	f[0] = 1;
	for(int i = 1;i <= n;i++){
		for(int j = m;j > 0;j--){
			for(int k = 1;k <= j/val[i];k++){
				f[j] += f[j-k*val[i]];
			}
		}
	}
	printf("%lld\n",f[m]);
}
int main(){
	//freopen("123.in","r",stdin);
	while(scanf("%d%d",&n,&m) != EOF){
		for(int i = 1;i <= n;i++) scanf("%d",val+i);
		solve();
	}
	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。

(来自老师的课件)

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_41162823/article/details/88055874