使用动态规划思想求解,即 dp[i][j] 表示将 i 个苹果放入到 j 个盘子的方法总数。
-
若 i<j,即苹果比盘子数小
- 比如将 2 个苹果放入 3 个盘子,必然会有一个盘子为空,即{0,x,y},其中一位固定为 0,不会影响最终的方案数,这和将 2 个苹果放入 2 个盘子的方案数目是一样的,即 {x,y}
- 因此有当 i<j 时,dp[i][j] = dp[i][i]
-
若 i>=j,即苹果数目不小于盘子数时,考虑是否有空盘子的情况(比如将 4 个苹果放入 3 个盘子)
- 若有空盘情况,相当于盘子数量少一个(因为固定一位是空盘,不会影响最终方案数目),即 {x,y,0},这对应着 dp[i][j-1]
- 若没有空盘的情况,对于 j 个盘子,相当于拿出来 j 个苹果,分配到每个盘子中1个,保证每个盘子分配到一个苹果。然后将剩下的 i-j 个苹果再分到 j 个盘子里,这对应着 dp[i−j][j]
- 因此有当 i>=j 时,dp[i][j] = dp[i][j-1] + dp[i−j][j]
-
边界条件
- 对于只有 1 个盘子的情况,分配方案只有 1 种,dp[i][1] = 1;
- 对于只有 0 个苹果的情况,分配方案只有 1 种,dp[0][j] = 1;
- 对于只有 1 个苹果的情况,分配方案只有 1 种,dp[1][j] = 1;
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int m;
int n;
while (cin >> m) {
cin >> n;
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
if (m == 0 || m == 1 || n == 1) {
cout << 1;
break;
}
// 边界条件
for (int i = 0 ; i <= m; i++) {
dp[i][1] = 1;
}
for (int j = 0 ; j <= n; j++) {
dp[0][j] = 1;
dp[1][j] = 1;
}
for (int i = 2; i <= m; i++) {
for (int j = 2; j <= n; j++) {
if (i < j) {
dp[i][j] = dp[i][i];
} else {
dp[i][j] = dp[i][j - 1] + dp[i - j][j];
}
}
}
cout << dp[m][n] <<endl;
}
}

京公网安备 11010502036488号