题目描述
解法:DP(C++)
记 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示 i i i 个苹果 j j j 个盘子时的方法数,初始时 d p [ 0 ] [ 0 ] = 1 dp[0][0]=1 dp[0][0]=1
转移方程 :
如果盘子的数量大于苹果的数量,那么空盘子其实是没有意义的,也就是 d p [ i ] [ j ] = d p [ i ] [ i ] dp[i][j]=dp[i][i] dp[i][j]=dp[i][i]
反之,即 j ≤ i j\leq i j≤i分两种情况:
- 所有盘子都放满苹果,那么还要剩下 i − j i-j i−j 个苹果要放 j j j 个盘,可能的方法数就是 d p [ i − j ] [ j ] dp[i-j][j] dp[i−j][j]
- 不是所有盘子都放苹果,换句话说就是至少有一个盘子没有放苹果,那么也就是 i i i 个苹果放 j − 1 j-1 j−1 个盘子,可能的方法数就是 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j−1]
为什么至少有一个盘子没有放苹果对应的就是 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j−1],而没有显示地考虑 d p [ i ] [ j − 2 ] dp[i][j-2] dp[i][j−2] 或 d p [ i ] [ j − 3 ] dp[i][j-3] dp[i][j−3] 呢 ?
因为 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j−1] 里包括了 d p [ i ] [ j − 2 ] dp[i][j-2] dp[i][j−2],而 d p [ i ] [ j − 2 ] dp[i][j-2] dp[i][j−2] 又包括了 d p [ i ] [ j − 3 ] dp[i][j-3] dp[i][j−3],以此类推
#include <bits/stdc++.h>
using namespace std;
int solution(int m, int n){
int dp[100][100];
dp[0][0] = 1;
for(int i=0;i<=m;i++) // apple
{
for(int j=1;j<=n;j++) // plate
{
if(j>i) dp[i][j] = dp[i][i];
else dp[i][j] = dp[i][j-1]+dp[i-j][j];
}
}
return dp[m][n];
}
int main()
{
int t, n, m;
cin >> t;
for(int i=0;i<t;i++)
{
cin >> m >> n;
cout << solution(m, n) << endl;
}
return 0;
}