递归的一些例子


   一、由整数1,2,3.....组成了一颗无限大的满二叉树,给出2个正整数,代表二叉树中的节点,求出这2个节点最近的公共祖先

int common(int  x , int y){
	if(x = y) return x;
	else if(x > y)
		return common(x/2,y);
	else 
		return common(x,y/2);
}
二、求逆波兰表达式

     逆波兰表达式是一种把运算符前置的算术表达式,例如(2 + 3) *4的逆波兰表示法为*+234。

 double exp(){
    char a[10];
    scanf("%s",a);
    switch(a[0]){
    case '+' : return exp() + exp();
    case '-' : return exp() - exp();
    case '*' : return exp() * exp();
    case '/' : return exp() / exp();
    default:return atof(a);
    }
}

    将逆波兰表达式转换成常规表达式输出,可以包含多余的括号

void exp(){
	char a[10];
	scanf("%s",a);
	switch(a[0]){
	case '+' : 
		cout << "(" ; 
		exp(); 
		cout << "+" ; 
		exp();
		cout << ")";
		break;
	case '-' : 
		cout << "(" ; 
		exp(); 
		cout << "-" ; 
		exp();
		cout << ")";
		break;
	case '*' : 
		exp(); 
		cout << "*" ; 
		exp();
		break;
	case '/' :
		exp(); 
		cout << "/" ; 
		exp();
		break;
	default  : cout << atof(a) ;
	}
}

三、放苹果

       把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问有多少种不同的分法?ps:5,1,1和1,5,1是同一种分法。  

       (1):当盘子数为1的时候,只有一种放法就是把所有苹果放到一个盘子里。
       (2):当苹果数为1的时候,也只有一种放法,注意题目中说明,盘子之间并无顺序,所以不管这个苹果放在哪个盘子里,结果都算一个。
       (3):当m<n时,因为此时最多只能放到m个盘子中去(一个里放一个),实际上就相当于把m个苹果放到m个盘子里一样,也就是f(m,m);
     (4):当m==n时,此时分两种情况讨论,一种是一个盘子里放一个,只是一种,第二种是,至少有一个盘子里不放苹果这就相当于是f(m,m-1);
      (5):当m>n时,也分两种情况讨论,一种是至少有一个盘子里不放苹果,这样子就相当于f(m,n-1),第二种是,先取出n个苹果一个盘子里放一个,再将剩下的m-n个苹果放到n个盘子里去,即f(m-n,n);
   

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

     可以用记忆化搜索,把f(m,n)换成f[m][n];

     这种做法可以统计总的放法,但是要得到每一种放法,还是要搜索+剪枝

     搜索就不说了,主要是剪枝提高了效率,当剩下的苹果平均放到剩余的盘子中的时候,每个盘子分的的苹果数目小于前一个盘子放置的苹果数目,这样就不满足我们给的要求ai-1<ai,所以加上条件

((m - w)/(n - k)) >= s[k - 1] 
void dfs(int k, int w){        //初始k=1,w=0;k表示现在已经用的盘子,w表示已经放了几个苹果
	 if(k == n){               //当最后一个盘子被放置苹果的时候我们进行判断	 
		 if(m - w >= s[k - 1]){
		    s[k] = m - w;
			int i;
			for(i = 1;i < n;i++)
				cout << s[i] << " ";
			cout << s[i] << endl;
		 }
		 return;
	  }
	  for(int i = 0;i <= m;i++){
		  if(i >= s[k - 1] && ((m - w)/(n - k)) >= s[k - 1] ){     //如果当前放置的苹果个数大于前一个盘子继续放置,后半部分是剪枝
			  s[k] = i;
			  w = w + i;
			  k = k + 1;
			  dfs(k,w);
			  w = w - i;
			  k = k - 1;
		  }
	  }
 }


  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值