当前位置:首页 > 题解目录 > 正文内容

【题解】放苹果(1)

亿万年的星光5年前 (2021-05-01)题解目录4724

【题目描述】

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

【输入】

第一行是测试数据的数目t(0≤t≤20)。以下每行均包含二个整数M和N,以空格分开。1≤M,N≤10。

【输出】

对输入的每组数据M和N,用一行输出相应的K。

【输入样例】

1
7 3

【输出样例】

8

【题目分析】

  • 比较经典的递归题目(排列组合)

  • 加上限制条件,一共可以催生出8种不同的题目(例如,盘子允许空或者不空就是两种情况)

  • 先分析样例,然后总结规律,最后用公式代替(递归的主要思路)

  • 也可以用递推规律去分析

  • 所有苹果都必须放完



【从样例分析递推规律】

按照题目样例,7(M)个苹果放到3(N)个盘子中。可能存在下面几种情况。

第一类:

7   0   0
6   1   0
5   2   0
4   3   0

第二类:

5   1   1
4   2   1
3   3   1
3   2   1

可以看出一共有8种,可以分成两类。


下面我们开始列举其他数据分类讨论寻找规律。

第一类:M<N时:

  • 假设1(M)个苹果放到2(N)个盘子中。只有1(M)种放法,而且至少空1(N-M)个盘子

  • 假设1  (M)  个苹果放到3 (N)个盘子中。只有1(M)种放法,而且至少空2(N-M)个盘子

  • 假设2(M)个苹果放到3(N)个盘子中。 只有2(M)种放法,而且至少空1(N-M)个盘子

  • 假设2(M)个苹果放到4(N)个盘子中。 只有2(M)种放法,而且至少空2(N-M)个盘子......

可以看出,当N>M时,放法只有M种。N的大小不影响不同的放法种数。如果放到递归中,也就是f(m,n)=f(m,m)

第二类:M>=N时:

从样例数据可以看出,M>=N时,可以继续分成两类,包含空盘子(0)和不包含空盘子的情况。那么,我们继续分析

  • 假设2(M)个苹果放到1(N)个盘子中。只有1种放法,没有空盘子

  • 假设3(M)个苹果放到1(N)个盘子中。只有1中放法,没有空盘子

  • 假设3(M)个苹果放到2(N)个盘子中。有2种放法(按照有没有空盘子分)。(3,0)和(2,1)

  • 假设4(M)个苹果放到2(N)个盘子中。有3种放法(按照有没有空盘子分)。(4,0)、(3,1)、(2,2)

  • 假设4(M)个苹果放到3(N)个盘子中。如果有一个空盘子,就是4个苹果放到2(N-1)个盘子中,那么跟上面的f(4,2)是一种情况。如果每个盘子至少一个。那么就是先相当于“先把每个盘子中放一个,剩余M-N个苹果放到N个盘子中”(注,此时M-N一定小于N,也就是跟第一类情况吻合)。那么这种情况就是

    F(M,N)=F(M,N-1)+F(M-N,N)。

    继续举例验证公式:

  • 假设5(M)个苹果放到3(N)个盘子中。F(5,3)一共有下面5种。

5 0 0
4 1 0
3 2 0

3 1 1
2 2 1

F(M,N-1)=F(5,2)=3种

5 0

4 1
2 3

  F(M-N,N)=F(2,3)=2种(第一类已经证明了)

所以,递归的结论是:

M<N时:F(M,N)=F(M,M)

M>=N时:F(M,N)=F(M,N-1)+F(M-N,N)

递归出口条件:

  • 当n=1时,所有苹果都必须放在一个盘子里,所以返回1;

  • 当m==0(没有苹果可放)时,定义为1种放法;

所以递归部分核心代码是:

int fun(int m, int n) {//m个苹果放在n个盘子中共有几种方法
    if(m==0 || n==1)
        return 1;
    if(n>m)
        return fun(m,m);
    else
        return fun(m,n-1)+fun(m-n,n);
}


【递推规律】

除了递归外,我们还可以尝试用递推去做,最好的办法就是“表格法”(打表法)




N=0N=1N=2N=3N=4N=5N=6
M=0x111111
M=1x1
11111
M=2x1
22222
M=3x1
2
33
33
M=4x13
4
555
M=5x13
5677
M=6x147910
11

注:并建议编程题用这种做法,即时画出表格,规律也不好总结


【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()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>k;
		sum=0;
		dfs(0,n,k);//因为可以有空盘,所以从0开始 
		cout<<sum<<endl;
	}
	return 0;
}


扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

标签: 递归
分享给朋友:

相关文章

质数环

【题目描述】有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。为了简便起见,我们规定每个素数环都从1开始。例如,下面就是6的一个素数环。1 4 3...

【题解】放苹果(2)

【题目描述】把M个同样的苹果放在N个同样的盘子里,不允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。【输入】第一行是测试数据的数目t(0≤t≤20)。以...

【题解】相关数

【题目描述】一个数与另一个数如果含有相同数字和个数的字符,则称两数相关。现有一堆乱七八糟的整数,里面可能充满了彼此相关的数,请你用一下手段,自动地将其剔除。【输入描述】每组数据前有一个N(<10...

【题解】山区建小学

【题目描述】政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0<i<...

【题解】东哥的杯子

【题解】东哥的杯子

【题目描述】话说在一场牛客练习赛中,东哥力压群雄,挣得第一,牛客为了奖励东哥的发挥,送他一个马克杯。奖励的马克杯是一个标准的圆台形状,它的上底为R1,下底为R2,高为H, 东哥向杯子里倒V毫升的水,你...

【题解】修改回文

【题目描述】如果一个字符串,顺读与倒读的内容一样,称这个字符串为回文。例如 aka 是一个回文,noon 也是一个回文。给定一个字符串,请计算最少需要修改多少个字符,才能...