递归较难题——分苹果问题

第四届程序设计大赛 苹果

Time Limit:1000MS  Memory Limit:65536K
Total Submit:90 Accepted:48

Description

把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

分析转自:http://uzone.univs.cn/blog_2984978_mgf8x9eow0qnb2wreow1.html

分析:放法要分盘子全放满了和没放满的情况。
由于当(1):苹果数少于盘子数时,此时把盘子减少一个,对结果没影响。(为什 么?试想如果10个苹果放1000个盘子,是不是很多盘子没用呢?嘿嘿)这样此时 fun(m,n)=fun(m,n-1);
    (2):苹果数少于盘子数,此时仍可以分成两种情况:放满和没有放满。
没放满:fun(m,n)转化成fun(m,n-1)(因为你有盘子没用)
放满 :放满即为每个盘子都有苹果,那么我把每个盘子的苹果拿一个出来结果仍然会是一样。此时的fun(m,n)转化成fun(m-n,m);(既然每个盘子必须有个苹果,那么这些苹果的存在与否可以当作不影响结果,比如拿5个苹果放2个盘子,又要满足每个盘子必须有个苹果的话那肯定有两个苹果不能动,必须放在盘子下,然后他们就与盘子融为一体,我们就当作看不见他们了。。。。。嘿嘿);
好了,函数进来盘子与苹果的数量关系每次都满足上面的两种情况,每次又归化成更简单的继续下去,那么很显然就想到了递归。
代码如下:
#include<stdio.h>
int fun(int m,int n)
{
         if(m<=1||n==1)
                   return 1;//为m可能为和n相等,此时如果要满足每个盘子都有的话只有一种放法。只有一个盘子也只有一种
         if(n==0)
                   return 0;
         if(n>m)//至少有一个盘子为空
                   return fun(m,n-1); 
         else//至少一个盘子为空 + 所有盘子都不为空
             return fun(m,n-1)+fun(m-n,n);
}
 int main()
{
         printf("%d\n",fun(7,3));
}

My  code:

#include<stdio.h>
int fun(int m,int n)
{
         if(m<=1||n==1)
                   return 1;//为m可能为和n相等,此时如果要满足每个盘子都有的话只有一种放法。只有一个盘子也只有一种
         if(n==0)
                   return 0;
         if(n>m)//至少有一个盘子为空
                   return fun(m,n-1); 
         else//至少一个盘子为空 + 所有盘子都不为空
             return fun(m,n-1)+fun(m-n,n);
}
 int main()
{
	 int m,t,n;
	 while(scanf("%d",&t)==1)
	 {
	 	while(t--)
	 	{
	 		scanf("%d%d",&m,&n);
	 		printf("%d\n",fun(m,n));
		 }
	 }
    return 0;
}


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值