题解 | #放苹果#
放苹果
https://www.nowcoder.com/practice/bfd8234bb5e84be0b493656e390bdebf
/*
本题虽然标记是简单, 但是我个人认为还是挺难的, 主要是状态不好确定, 状态内的各个子问题和原问题好像没说明区别
然后是状态确定好了, 但是方程不好确定. 用递归暴力破解比较好理解dp[i][j] = dp[i-j][j] + dp[i][j-1]
左边无限递归遍历左子树就是保证每个盘子都有一个分到极限, 右边右子树无限递归循环就是只有一个盘子装苹果
综合下来就是一个盘子到j个盘子装苹果的方法之和, 然后就是注意边界 i<0,j<=0 reture 0;//非法数据返回0 i==1 || j==1 || i==0 reture 1;
1个苹果 一个盘子 0个苹果,盘子为空
将以上思路放到动态规划的理解就是
i<j dp[i][j] = dp[i][i]
i>=j dpij = dp[i-j][j] + dp[i][j-1]
每个盘子都有苹果 至少一个盘子没有苹果
边界条件
dp[0][j] = 1; dp[1][j] = 1;
dp[i][1] = 1;
*/
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
//设置动态规划数组dp[i][j]代表i个苹果放入j个盘子的放法
int [][]dp = new int[m+1][n+1];
//dp数组边界初始化
//苹果为0时, 只有一种
//苹果为1时, 只有一种
//盘子为1时只有一种
for (int i = 0; i <= n; i++)
{
dp[0][i] = 1;
dp[1][i] = 1;
}
for (int i = 0; i <= m; i++)
{
dp[i][1] = 1;
}
//通过dp方程, 推导dp数组
//i<=j, dp[i][j] = dp[i][i]
//i>j , dp[i][j] = dp[i-j][j] + dp[i][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][j] + dp[i][j-1];
}
}
}
System.out.println(dp[m][n]);
}
}
