【ACM暑假培训】2、递归算法···放苹果···

这篇博客介绍了如何使用递归算法解决将M个苹果放入N个盘子的不同分法问题。讨论了递归的基本概念,并给出了C语言相关的学习资源。文中提供了一个避免重复分法的程序思路,包括不同情况的递归处理,如苹果数小于篮子数、大于篮子数等。同时,博主鼓励读者提出错误和留言交流。

递归算法

今天我们学习了用for循环去枚举每一种可能的答案。然而,有些题目用for循环是很难枚举出每一种情况的。所以明天我们要学习递归算法。这是明天要讲的题目,大家可以先看一下,想一下。

c语言课本“函数的递归调用”那一节可以作为学习的参考资料。

欢迎大家指正我程序中的错误,我会虚心接受;欢迎大家留言,我会认真回复的。

—————————————————分割线———————————————————————

 

1、放苹果

问题描述

把 M 个同样的苹果放在N 个同样的盘子里,允许有的盘子空着不放,问共有多少

种不同的分法?(用K 表示)注意:5,1,1 和1,5,1 是同一种分法。

输入数据

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含两个整数M 和N,以

空格分开。1<=M,N<=10。

输出要求

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

输入样例

1

73

输出样例

8

方法1:

为了使程序出现5,1,1与1,1,5这类重复,程序t记录前一次分的苹果数,后一次分的苹果永远小于等于前一次分的。

如果剩余苹果为0篮子还有剩余,满足题意。

//放苹果
#include<stdio.h>
int M,N,K;
int m,k=0;//n:剩余盒子数   k:用的第k个盒子
int a[100]={0};

void DFS(int m,int t)//m:剩余苹果数,t:上次分的苹果数
{
    if (m==0&&k<=N)
	{
		//for(int j=0;j<k;j++)
		//	printf("%d ",a[j]);
	    //printf("\n");
		K++;
	}
	else
	{
		for(int i=M;i>0;i--)
			if(i<=t&&i<=m)
			{ 
				m=m-i;
		        a[k++]=i;
		        DFS(m,i);
		        a[--k]=0;
		        m=m+i;
			}
	}
		 
}

void main()
{
   int t;
   scanf("%d",&t);
   for(int i=0;i<t;i++)
   {
      K=0;
	  scanf("%d %d",&M,&N);
      DFS(M,M);
	  printf("%d\n",K);
   }
}




方法2

      要将m个苹果放进n个篮子有三种情况:

      1、若苹果数<篮子数,则f(m,n)=f(m,m),有n-m个篮子里必定没苹果,其余篮子里可能有,也可能没有。

      2、若苹果数>篮子数,则又分两种情况:

              1.所有的篮子里都有苹果f(m-n,n);

              2.有个篮子没有苹果f(m,n-1);

  <感觉这种方法像递推,,不过目前还不清楚是不是。。。>

      3、篮子数为1或苹果数为0,则只有一种分法。

#include<stdio.h>

int apple(int m,int n)
{
    if(m==0||n==1)
		return 1;
    if(m<n)
		return (apple(m,m));
	else
		return (apple(m-n,n)+apple(m,n-1));
}


void main()
{
    int m,n,t;
	scanf("%d",&t);
	for(int i=0;i<t;i++)
	{
     	scanf("%d %d",&m,&n);
	    printf("%d\n",apple(m,n));
	}
}

    

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值