计数DP


计数类DP

整数划分

可看作是完全背包问题的改版,将1~n的数看作体积,每个物品使用无限次,恰好能装满背包体积n的总方案数。

注意初始化时,我们要求的与完全背包不同,完全背包要求最大的价值,该题要求最大的方案数,因此我们至少有一种方案,应该全部初始化为1。

状态表示:f[i] [j]表示使用前i个整数恰好拼成j的方案数。

因此有

f[i][j] = f[i - 1][j] + f[i - 1][j - i] + f[i - 1][j - 2 * i] + ...;
f[i][j - i] = f[i - 1][j - i] + f[i - 1][j - 2 * i] + ...;

由完全背包的公式推得:

f[i][j] = max(f[i][j], f[i - 1][j] + f[i][j - i]);

再加上一维优化:

#include <bits/stdc++.h>
using namespace std;

const int N = 1010, mod = 1e9 + 7;
int q[N];

int main()
{
    int n;
    cin >> n;
    q[0] = 1; // 初始化状态为1

    for (int i = 1; i <= n; i ++ ){
        for (int j = i; j <= n; j ++ ){
            q[j] = (q[j] + q[j - i]) % mod;
        }
    }

    cout << q[n] << endl;
}

文章作者: Cedeat
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Cedeat !
  目录