时/空限制:1s / 64MB
题解(dfs):
- n个盘子中分别放多少个苹果
- 同一种分法,因此,每个盘子中放苹果的数量必须不变或者递增,到最后一个盘子的时候,就可以判断了,不需要到最后一个的下一个
- sum记录当前已经多少个苹果,ans记录方案数
#include <iostream>
using namespace std;
int m, n;
int ans, sum;
void dfs(int u, int last) {
if (u == n) {
if (m - sum >= last) {
ans ++ ;
}
return ;
}
for (int i = last; i <= m; ++ i) {
sum += i;
dfs(u + 1, i);
sum -= i;
}
}
int main() {
while (cin >> m >> n) {
ans = sum = 0;
dfs(1, 0);
cout << ans << endl;
}
}
题解(dp):
- 前i个盘子中放j个苹果的方案数
- 如果盘子数量n大于苹果数量m,说明至少有n-m个盘子中是空的,相当于m个盘子放m个苹果
- 如果小于等于,分成两种情况,一种是有一个盘子不放,也就是f[i - 1][j],还有一种情况就是所有盘子都放,因此,等价于f[i][j-i];两者相加
- 初始化:1个盘子时,所有苹果数量都合法(0个盘子不合法);0个苹果时,所有盘子数量都合法
#include <iostream>
using namespace std;
const int N = 15;
int f[N][N];
int main() {
int m, n;
while (cin >> m >> n) {
for (int i = 0; i <= m; ++ i) {
// f[0][i] = 1; // false,非法
f[1][i] = 1;
}
for (int i = 0; i <= n; ++ i) {
f[i][0] = 1;
}
for (int i = 1; i <= n; ++ i) {
for (int j = 1; j <= m; ++ j) {
if (i > j) {
f[i][j] = f[j][j];
} else { // 注意i == j的情况得分到下面这个情况,仍然算 有盈余
f[i][j] = f[i - 1][j] + f[i][j - i];
}
}
}
cout << f[n][m] << endl;
}
}