计数类DP
1. 计数类DP
定义
- 此类问题一般让我们求解方案数。
2. AcWing上的计数类DP题目
AcWing 900. 整数划分
问题描述
-
问题链接:AcWing 900. 整数划分
分析
- 本题存在两种解法,这里都讲解一下。
背包解法
-
存在
n
个物品,这n
个物品的体积分别是1、2、...、n
,给定一个容量为n
的背包,其恰好将背包填满的方案数目,类似于完全背包问题。 -
分析如下:
- 类似于完全背包,可以优化成一维,注意第二层循环体积需要从小到大循环。
解法2
- 分析如下:
- 最后的答案是
f[n][1]+f[n][2]+...+f[n][n]
。
代码
- C++
// 解法1
#include <iostream>
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n;
int f[N];
int main() {
cin >> n;
f[0] = 1; // 没选物品,体积为0对应1种方案
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
f[j] = (f[j] + f[j - i]) % mod;
cout << f[n] << endl;
return 0;
}
// 解法2
#include <iostream>
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n;
int f[N][N];
int main() {
cin >> n;
f[0][0] = 1; // 和为0,0个数对应的方案数是1
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
f[i][j] = (f[i - 1][j - 1] + f[i - j][j]) % mod;
int res = 0;
for (int i = 1; i <= n; i++) res = (res + f[n][i]) % mod;
cout << res << endl;
return 0;
}