程序设计与算法----递归之放苹果问题

问题描述
例题:放苹果
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问公有多少种不同的分法?5,1,1和1,5,1是同一种分法
输入
第一行是测试数据数目t(0<=t<=20),以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10
输入
第一行是测试数据的数目t(0<=t<=20)。以下每行均包含两个整数M和N。以空格分开,1<=M,N<=10
对输入的每组数据M和N.用一行输出相应的K

样例输入

1
7 3

样例输出

8

算法思想
由于这里M和N的规模比较小,所以我们可以用递归来解决。递归算法里面有很多重复计算,我们得使用动态规划才能算
*设i个苹果放在k个盘子里方法总数是f(i,k),则:
由于我们盘子和苹果都是无差别的,我们可以考虑
当k>i时,f(I,k)=f(I,i)
k<=i时,总方法=有盘子为空的放法+没盘子为空的放法
f(I,k)=f(I,k-1)+f(i-k,k);
边界条件?

考虑到,现在要把i个苹果放在k个盘子里面,i>=k,当所有的盘子都不为空,此时,我们可以往所有的盘子里面放1个苹果,放完以后,还剩下i-k个,接下来就变成i-k个苹果放到k个盘子里的放法总数。
递归函数的终止条件
当m=0,即没有苹果要放的时候,表示苹果已经放完了,不往盘子里放苹果,盘子全为空,return 1。当n=0,即没有盘子要放了,此时return 0
注意,m和n的变化,防止m和n无法减到0,然后无穷递归,这里m不会减小到比0还小的数。

程序代码

#include<iostream>
using namespace std;
#define MAXSIZE 21 
int layApple(int m,int n){
	//将0个苹果放在n个盘中,有1种放法,即全部为空。 
	if(m==0){
		return 1;
	}
	//将m个苹果放在0个盘子中,没有放法。 
	if(n==0){
		return 0;
	}
	//将m个苹果放在n个盘子中,我们可以分情况讨论
	//1.当m小于n时,即苹果数小于盘子数,由于苹果盘子均相同,所以m个苹果放在n个盘子中,相当于m个苹果放在m个盘子中 
	if(m<n){
		return layApple(m,m);	 
	}
	//2.当m大于n时,即苹果数大于盘子数,这时候又可以将其分为两种情况,两种情况所产生的方法总和 
	//2.1.有盘子为空,则最少有1个盘子为空,那么方法总数等于将m个苹果放在n-1个盘子中
	//2.2.没有盘子为空,则相当于每个盘子都放了一个,转化为m-n个苹果放在了n个盘子中。 
	else{
		return layApple(m-n,n)+layApple(m,n-1);
	}
}
int main(){
	int m,n;		//m个苹果放在n个盘子里 
	int *result=new int[MAXSIZE];
	int t;			//测试数据的数目
	cin>>t;
	for(int i=0;i<t;i++){
		cin>>m>>n;
		result[i]=layApple(m,n);
	} 
	for(int i=0;i<t;i++){
		cout<<result[i]<<endl;
	} 
	return 0;
} 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值