1371. 货币系统-dp背包问题
给定 V种货币(单位:元),每种货币使用的次数不限。
不同种类的货币,面值可能是相同的。
现在,要你用这 V种货币凑出 N 元钱,请问共有多少种不同的凑法。
输入格式
第一行包含两个整数 V 和 N。
接下来的若干行,将一共输入 V 个整数,每个整数表示一种货币的面值。
输出格式
输出一个整数,表示所求总方案数。
数据范围
1≤V≤25,
1≤N≤10000
答案保证在long long
范围内。
输入样例:
3 10
1 2 5
输出样例:
10
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
// 定义长整型别名,方便后续使用
typedef long long LL;
// 定义常量 N 和 M,分别表示物品数量上限和背包容量上限
const int N = 30, M = 10010;
// n 表示物品数量,m 表示背包容量
int n, m;
// v 数组用于存储每个物品的体积
int v[N];
// f 数组用于存储状态,f[i][j] 表示前 i 个物品装满容量为 j 的背包的方案数
LL f[N][M];
int main()
{
// 从标准输入读取物品数量 n 和背包容量 m
scanf("%d%d", &n, &m);
// 循环读取每个物品的体积
for (int i = 1; i <= n; i ++ ) scanf("%d", &v[i]);
// 初始化状态,当没有物品且背包容量为 0 时,方案数为 1
f[0][0] = 1;
// 动态规划过程,枚举每个物品
for (int i = 1; i <= n; i ++ )
// 枚举背包的每个容量
for (int j = 0; j <= m; j ++ )
{
// 不选择第 i 个物品的方案数
f[i][j] = f[i - 1][j];
// 如果当前背包容量 j 大于等于第 i 个物品的体积 v[i]
if (j >= v[i])
// 选择第 i 个物品的方案数,累加到 f[i][j] 中
f[i][j] += f[i][j - v[i]];
}
// 输出前 n 个物品装满容量为 m 的背包的方案数
printf("%lld\n", f[n][m]);
return 0;
}