目录
题目描述
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分发(5,1,1和1,1,5是同一种方法)
输入输出格式
输入格式:
第一行是测试数据的数目t(0 <= t <= 20),以下每行均包括二个整数M和N,以空格分开。1<=M,N<=10
输出格式:
对输入的每组数据M和N,用一行输出相应的K。
输入输出样例
输入样例#1: 复制
1
7 3
输出样例#1: 复制
8
输入样例#2: 复制
3
3 2
4 3
2 7
输出样例#2: 复制
2
4
2
这题和数的划分做法相近,可以用DFS和DP,但是要注意该题的盘子是可空的。
DP
F[ i ][ j ]表示将 i 份分在 j 个盘子里
F[ 0 ][ j ]=F[ 1 ][ i ]=1 当苹果数量为0或1时只有一种方法
F[ i ][ 1 ]=1 当只有一个盘子时只有一种方法
- 当 i<j 时,也就是苹果数量小于盘子数量时,F[ i ][ j ]=F[ i ][ i ] 因为 i 个苹果最多只能占用 i 个盘子
- 当i>=j时,F[ i ][ j ]=F[ i-j ][ j ] + F[ i ][ j-1 ]
F[ i ][ j-1 ] 表示j个盘子中有空盘,取出空盘
F[ i-j ][ j ] 则是每个盘子先放一个苹果的策略
代码:
#include<bits/stdc++.h>
using namespace std;
int f[15][15];//f[i][j]即为i个苹果放在j个盘子里的方案数
int m,n,ans;
int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--)
{
cin >> m >> n;
ans=0;
memset(f,0,sizeof(f));//清空f数组
for(int i=1;i<=n;i++)
f[0][i]=f[1][i]=1;
for(int i=1;i<=m;i++)
f[i][1]=1;]
for(int i=2;i<=m;i++)
for(int j=2;j<=n;j++)
if(i<j)//如果苹果比盘子还少
f[i][j]=f[i][i];//等于i个苹果放在i个盘子里
else
f[i][j]=f[i-j][j]+f[i][j-1];//对于每一次,有两种做法:
//1:j个盘子里都放 1个,即 f[i-j][j]
//2:都不放,即 f[i][j-1]
cout << f[m][n] << endl;//输出
}
return 0;
}
DFS
#include<iostream>
using namespace std;
int t,n,k;
int f[11][11];
int sum;
void dfs(int step,int num,int tar)
{
if(tar==1)
{
sum++; return ;
}
for(int i=step;i<=num/tar;i++)
dfs(i,num-i,tar-1);
}
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n>>k;
sum=0;
dfs(0,n,k);//因为可以有空盘,所以从0开始
cout<<sum<<endl;
}
return 0;
}