洛谷P2386 - 放苹果

题目描述

P2386 放苹果

解法: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 ji分两种情况:

  • 所有盘子都放满苹果,那么还要剩下 i − j i-j ij 个苹果要放 j j j 个盘,可能的方法数就是 d p [ i − j ] [ j ] dp[i-j][j] dp[ij][j]
  • 不是所有盘子都放苹果,换句话说就是至少有一个盘子没有放苹果,那么也就是 i i i 个苹果放 j − 1 j-1 j1 个盘子,可能的方法数就是 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j1]

为什么至少有一个盘子没有放苹果对应的就是 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j1],而没有显示地考虑 d p [ i ] [ j − 2 ] dp[i][j-2] dp[i][j2] d p [ i ] [ j − 3 ] dp[i][j-3] dp[i][j3] 呢 ?

因为 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j1] 里包括了 d p [ i ] [ j − 2 ] dp[i][j-2] dp[i][j2],而 d p [ i ] [ j − 2 ] dp[i][j-2] dp[i][j2] 又包括了 d p [ i ] [ j − 3 ] dp[i][j-3] dp[i][j3],以此类推

#include 

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;
}

你可能感兴趣的:(题解)