文章目录
0. 前言
相关:
1. 01背包求方案数
将 M
看作背包容量,每个数看成一个物品,Ai
看成是体积。本题即转化为:求出总体积恰好是 M
的方案数。
思路:
- 状态表示:
f[i,j]
:所有只从前i
个物品中选,且总体积不超过j
的方案的数量
- 状态计算:
- 和 01 背包一致,根据最后一步第
i
个物品选还是不选分类 - 不包含物品
i
的所有选法:f[i][j] = f[i-1][j]
- 包含物品
i
的所有选法f[i][j] = f[i-1][j-vi]
- 状态转移方程:
f[i][j] = f[i-1][j]+f[i-1][j-vi]
- 和 01 背包一致,根据最后一步第
- 状态初始化及答案:
f[0]=1
,初始M
为 0 时,一个不选也是一种方案,其它均为 0- 答案即为
f[m]
一维代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10005;
int n, m;
int f[N];
int main() {
cin >> n >> m;
f[0] = 1;
for (int i = 0; i < n; ++i) {
int v;
cin >> v;
for (int j = m; j >= v; --j)
f[j] += f[j - v];
}
cout << f[m] << endl;
return 0;
}
二维代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10005;
int n, m;
int v[N];
int f[N][N];
int main() {
cin >> n >> m;
f[0][0] = 1;
for (int i = 1; i <= n; ++i) cin >> v[i];
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= m; ++j) {
f[i][j] = f[i - 1][j];
if (j >= v[i]) f[i][j] += f[i - 1][j - v[i]];
}
}
cout << f[n][m] << endl;
return 0;
}