题目描述
一个正整数可以划分为多个正整数的和。
比如 n = 3 时: 共有三种划分方法。
- 3 = 3
- 3 = 1+2
- 3 = 1+1+1;
给出一个正整数,问有多少种划分方法。
输入格式
一个正整数 n
输出格式
一个正整数,表示划分方案数
样例输入
3
样例输出
3
数据范围
0 < n ≤ 100
题解一
动态规划:
f[i][j]
:
集合
:只从前 i 个物品中选,且总体积恰好为 j 的方案的集合属性
:数量
#include <iostream>
using namespace std;
const int N = 110;
int f[N][N];
int main()
{
int n;
cin >> n;
f[0][0] = 1; // 一个物品都不选,即体积为 0,也是一种方案
for (int i = 1; i <= n; i ++)
for (int j = 0; j <= n; j ++)
for (int k = 0; k * i <= j; k ++) // 枚举每个数字选几次
f[i][j] += f[i - 1][j - k * i];
cout << f[n][n] << endl;
return 0;
}
题解二
动态规划(优化1.0):
偷个懒,直接把我之前完全背包博客中的图片搬了过来,有点区别,但是也可以参考一下。
#include <iostream>
using namespace std;
const int N = 110;
int f[N][N];
int main()
{
int n;
cin >> n;
f[0][0] = 1;
for (int i = 1; i <= n; i ++)
for (int j = 0; j <= n; j ++)
{
f[i][j] = f[i - 1][j];
if(j >= i) f[i][j] += f[i][j - i];
}
cout << f[n][n] << endl;
return 0;
}
题解三
动态规划(优化2.0):
在优化1.0中
f[i][j] += f[i][j - i]
,只用到了第 i 层
的状态,所以可以从小到大枚举体积,同时删去第一维状态。
#include <iostream>
using namespace std;
const int N = 110;
int f[N];
int main()
{
int n;
cin >> n;
f[0] = 1;
for (int i = 1; i <= n; i ++)
for (int j = i; j <= n; j ++)
f[j] += f[j - i];
cout << f[n] << endl;
return 0;
}