这个问题可以使用动态规划来解决。我们可以定义一个二维数组 dp[i][j]
,其中 dp[i][j]
表示将 i
个梨子分配到 j
个盘子中的方法数。
首先,考虑边界情况:
- 当梨子数
i
等于 0 时,无论有多少个盘子j
,都只有一种方法,即将所有盘子都空着。 - 当只有一个盘子
j
时,无论有多少个梨子i
,都只有一种方法,即将所有梨子都放在这个盘子里。
然后,我们可以使用递推关系来填充 dp
数组:
- 当梨子数
i
小于盘子数j
时,无法进行合理的分配,此时dp[i][j]
应该等于将i
个梨子分配到i
个盘子中的方法数,因为一个盘子最多只能放一个梨子,多余的盘子没有用。即dp[i][j] = dp[i][i]
。 - 当梨子数
i
大于等于盘子数j
时,我们可以考虑两种情况:- 至少有一个盘子为空,这种情况下,我们将梨子分配到
j - 1
个盘子中,方法数为dp[i][j - 1]
。 - 每个盘子都至少有一个梨子,这种情况下,我们将
j
个盘子中的一个梨子拿出来,剩下的梨子分配到剩下的j - 1
个盘子中,方法数为dp[i - j][j]
。
- 至少有一个盘子为空,这种情况下,我们将梨子分配到
思路清楚后,定义二维数组的时候,编译出现了问题,就是在使用 vector<vector<int>>
定义二维向量时,尝试编译器解释 >>
为右移操作符而导致的。为了解决这个问题,你可以在 >>
之间添加一个空格,改为 vector<vector<int> >
,以明确告知编译器这是模板参数列表的结束标记。
下面这个代码,之前交上去都是对的,后面再交就出现不对了,找了半天是为什么
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--)
{
int m,n;
cin >> m >> n;
//定义一个大小为(m+1)x(n+1)的二维数组,并将所以元素初始化为0
vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));
//边界情况
//只有一个盘子 ,j=1
for(int i=0;i<=m;i++)
{
dp[i][1]=1;
}
//梨子数为0,i=0
for(int j=0;j<=n;j++)
{
dp[0][j]=1;
}
//递归填充 ,分情况计算dp[i][j]的值
for(int i=1;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];
}
return 0;
}
原因就是输入包含多组测试样例,还差一个外循环
下面是最新更新的正确代码
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
while(cin >> t)
{
while(t--)
{
int m, n;
cin >> m >> n;
//定义一个大小为(m+1)x(n+1)的二维数组,并将所有元素初始化为0
vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));
//边界情况
//只有一个盘子 ,j=1
for(int i = 0; i <= m; i++)
{
dp[i][1] = 1;
}
//梨子数为0,i=0
for(int j = 0; j <= n; j++)
{
dp[0][j] = 1;
}
//递归填充 ,分情况计算dp[i][j]的值
for(int i = 1; i <= m; i++)
{
for(int j = 2; j <= n; j++)
{
if(i < j)
{
dp[i][j] = dp[i][j-1];
}
else
{
dp[i][j] = dp[i][j-1] + dp[i-j][j];
}
}
}
cout << dp[m][n] << endl;
}
}
return 0;
}