把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
Input
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
Output
对输入的每组数据M和N,用一行输出相应的K。
Sample Input
1
7 3
Sample Output
8
第一种解法:搜索
M个苹果放N个盘子里,盘子可以为空。直接搜吧,主要难点就是如何控制怎么才能筛选出不同的分法。
怎么筛呢?我们分析一波样例
0,0,7
0,1,6
0,2,5 、1,1,5
0,3,4、 1,2,4
1,3,3
2,2,3
看出规律来了吗??
后一个盘子的苹果数都 >= 前一个盘子的苹果数
根据这点咱们就可以得到答案。
因为最多才10个盘子,咱们就可以开一个数组,记录每个盘子的苹果数,后面的盘子的苹果数只要比前一个大就行,附上代码
import java.util.Scanner;
public class Main {
int m,n,sum;
int[] g = new int[15];
public static void main(String[] args) {
Main s = new Main();
int k;
Scanner cin = new Scanner(System.in);
k = cin.nextInt();
while(k>0)
{
k--;
s.sum=0;
s.init(); //g数组初始化
s.m = cin.nextInt(); //苹果数
s.n = cin.nextInt(); //盘子数
s.dfs(s.m,1);
System.out.println(s.sum);
}
}
public void init()
{
for(int i=0;i<15;i++)
{
g[i]=0;
}
}
public void dfs(int num,int top)
{
if(top==n) //到最后一个盘子时
{
if(num>=g[top-1]) //判断剩下的苹果数是否比前一个盘子苹果数多 多的话分法+1
{
sum++;
}
return ;
}
for(int i=0;i<num;i++)
{
if(i>=g[top-1])
{
g[top]=i;
dfs(num-i,top+1);
g[top]=0;
}
}
}
}
第二种解法:dp
我们多手动写几次就能找出规律来了,拿样例来说
7 3,那他的值就等于 7 2的值+4 3的值,所以可以定义一个二维数组来存
g[m][n] = g[m][n-1]+g[m-n][n]
但是还有一种情况 m-n的值比n的值更小,举个例子
g[4][3] = g[4][2]+g[1][3] 这是不成立的 ,因为g[1][3]这个值是不存在的(m>=n)
所以这个时候的规律就变成
g[m][n] = g[m][n-1]+g[m-n][m-n]
g[4][3] = g[4][2]+g[1][1] 成立 下面给代码
import java.util.Scanner;
public class Main {
int m,n,sum;
int[][] g = new int[15][15];
public static void main(String[] args) {
Main s = new Main();
Scanner cin = new Scanner(System.in);
int k = cin.nextInt();
s.fig();
while(k>0)
{
k--;
s.sum=0;
s.m = cin.nextInt(); //苹果数
s.n = cin.nextInt(); //盘子数
System.out.println(s.g[s.m][s.n]);
}
}
public void fig()
{
g[0][0]=1; //g[1][1] = g[1][0] +g[0][0] 先给它初始值 后面再变回来
//你也可以不这样 但是需要在for循环里面加一些判断
for(int i=1;i<=10;i++)
{
for(int j=1;j<=i;j++)
{
if(i-j<j)
{
g[i][j]=g[i][j-1]+g[i-j][i-j];
}
else
{
g[i][j]=g[i][j-1]+g[i-j][j];
}
}
}
g[0][0]=0; //这里就改回来
}
}