蓝桥杯——递归问题

本文深入探讨递归问题,通过汉诺塔、第39级台阶、李白打酒等经典实例,阐述递归的终止条件和边界值界定。同时,讨论了在不同场景下如何运用递归来解决实际问题,如抽签组合和限制条件下的国家组合问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深入递推,逐级回退

递归问题    深搜dfs   在有条件的情况下试探各种情况  找出口 

递归的终止条件

递归函数参数边界值的界定

 

汉诺塔问题Hanoi

/*思想
1.src上的n-1个盘子移到medium
2.src剩下的一个最大的盘子移到dest
3.medium上的n-1个盘子移到dest

*/
//把src最上面的一个盘子移到dest
void move(char src, char dest){
	
	cout<<src<<"—>" <<dest<<endl;
}

//把n个盘子从src移到dest,以medium为中介
void hanoi(int n, char src, char medium, char dest)
{
	if(n==1)  move(src,dest);    //边界条件
	else{
		hanoi(n-1, src, dest, medium);
		move(src, dest);
		hanoi(n-1, medium, src, dest);
	}
} 

hanoi(3,'A','B','C');

理解每步的调用过程

 

 

2013-3 第39级台阶

 每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替。
 最后一步是迈右脚,也就是说一共要走偶数步。共有多少种方案? 

递归的终止条件


/*
	f(n=39){ return f(n-1)+f(n-2); } 
	n:剩下的台阶数  为0时停止递归 
	step:走过的步数 	判断是否为偶数(题目要求) 
*/

void f(int n, int step)
{
	if(n<0) return;
	if(n==0 && step%2==0) //边界条件(+符合要求的结果)
	{
		ans++;
		return;
	}
	f(n-1,step+1);
	f(n-2,step+1);
} 

f(39,0)
//51167078

这个二叉树的每个叶子节点都是一种情况 

 

2014-3 李白打酒

酒壶中有酒2斗,逢店加一倍,遇花喝一斗。 
他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
李白遇到店和花的次序,共有多少种可能?

递归函数参数边界值的界定

void f(int shop, int flower, int beer)
{
	if( shop==0 && flower==1 &&beer==1 ) ans++;   //边界条件
	if( shop>0 )	f(shop-1, flower, beer*2);    //if(shop>0) 和  if(flower>0)
	if( flower>0 )	f(shop, flower-1, beer-1);
}

f(5,10,2);
//14

 

2014-5  打印图形

void f(char a[][N], int rank, int row, int col)
{
    //边界条件
	if(rank==1){
		a[row][col] = '*';
		return;
	}
	
	int w = 1;
	int i;
	for(i=0; i<rank-1; i++) w *= 2;  //w=32  程序填空题  w是一个关键的值
	
	f(a,rank-1,row,col+w/2);     //处理顶上的三角形
	f(a, rank-1, row+w/2, col);    //a,5,16,0  左下三角形
	f(a, rank-1, row+w/2, col+w);    //a,5,16,32  右下三角形
}

f(a,6,0,0);

 

2016-5-抽签

X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。
....

那么最终派往W星的观察团会有多少种国别的不同组合呢?

下面的程序解决了这个问题。
数组a[] 中既是每个国家可以派出的最多的名额。
程序执行结果为:
DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
....
(以下省略,总共101行)

程序填空的递归题,注意参数的含义,变化方向 

#include <stdio.h>
#define N 6
#define M 5
#define BUF 1024
/*
k是a[]的下标   k变大 
m代表人数,初值为5   m变小 
b[]缓冲字符串  
*/
void f(int a[], int k, int m, char b[])
{
	int i,j;
	                                          
	if(k==N){                                                                        
		b[M] = 0;   //字符串结尾的标志 
		if(m==0) printf("%s\n",b);
		return;
	}
	
	for(i=0; i<=a[k]; i++){ //尝试从k国家排出i个人 
		for(j=0; j<i; j++)  //填充buf,有i人就填i个国家符号 (k+'A')
		   b[M-m+j] = k+'A';  
        f(a,k+1,m-i,b);	    //递归填空,参数的含义,变化方向 
	}
}
int main()
{	
	int  a[N] = {4,2,2,1,1,3};  	//a[] 每个国家可以派出的最多的名额     N  6个国家数 
	char b[BUF];					//b[]  观察团人员组成           M  5人观察团 
	f(a,0,M,b);					
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值