编程只是工具,是用来处理问题的。学习中老师提出两个问题让试着用递归解决。
第一题
汉诺塔问题
有三根柱子A、B、C,其中A柱上按大小有序排列N个圆盘,底部最大,顶部最小。要求把圆盘从下面开始按大小顺序重新摆放在C柱上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。求从A柱往C柱上挪动N个圆盘最少需要多少步。
这个问题很明显可以如此分析,将圆盘分为最低部一个,和上面N-1个两部分,只需将上面N-1个圆盘放在B柱上,再将底部圆盘放在C柱上,然后将B柱上N-1个圆盘放到C柱上即可。相应的,上面N-1个,可以分解为第N-1个和其上方N-2个的两部分。
由以上分析可知,第N个圆盘的最少步数为(第N-1个圆盘的最少步数)+1+(第N-1个圆盘的最少步数)。明显可以通过大事化小的思路解决,与递归的思路相符,以下测试:
#include <stdio.h>
//汉诺塔问题最优步数求解。
int tow(int x)
{
if (x > 1)
return 2 * tow(x - 1) + 1; //重复前一步骤并将底盘放入目标杆。
else
return 1;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", tow(n));
return 0;
}
输入n=3层时,函数tow(3)执行 return 2*tow(3 -1) +1,进入下一层tow(2),执行return 2*tow(2-1) +1,进入下一层tow(1),执行return 1。回到上一层结果 return 2*1+1(=3),再回到上一层结果 return 2*3 +1(=7)。
经多次测试,计算结果正确。
第二题
青蛙跳台阶问题
有个青蛙,一次可以跳1层台阶,也可以跳2层台阶。问它跳到N层台阶有多少种可能的跳法。
这个问题也比较简单。第一层只有一种可能,跳1层。第二层只有两种可能,跳1层或跳2层。第N(N>2)层也只有两种可能,分别是从(N - 1)层再跳1层,从(N-2)层再跳2层。即第N层可能的跳法数量为(N-1)的可能跳法数量加上(N-2)的可能跳法数量。也符合递归的思路,把大事化小。以下测试:
#include <stdio.h>
//青蛙跳台阶,每次跳1层或2层,到n层可能的跳法数量。
int step(int x)
{
if (x > 2)
return step(x - 1) + step(x - 2); //由之前一层+1层,或由之前两层+2层。
else if (x == 2)
return 2;
else
return 1;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", step(n));
return 0;
}
分析思路同上例。
输入n=4层时,函数step(4)执行return step(3) +step(2); 函数step(3)执行return step(2)+step(1);函数step(2)执行返回2;函数step(1)执行返回1;则回到上一级,step(3)=2+1=3;再回到上一级,step(4)=3+2=5。
此类问题解决思路都是先将后续可能分解成更小级别的问题,即把大事化小。