汉诺塔问题
一块板上有三根针 A、B、C。A 针上套有 64 个大小不等的圆盘,按照大的在下、小的在上的顺序排列,要把这 64 个圆盘从 A 针移动到 C 针上,每次只能移动一个圆盘,移动过程可以借助 B 针。但在任何时候,任何针上的圆盘都必须保持大盘在下,小盘在上。从键盘输入需移动的圆盘个数,给出移动的过程。
思路:在简单的尝试之后我们会发现一个规律,要想把n个盘子都移到C柱子上,首先要把最大的盘子移到C柱子上,要把最大的盘子移到C上就必须把最大的上面的n-1个盘子移到B柱子上,待最大的盘子移到C柱子上,然后再将n-1个盘子移到C柱子上。如下三步:
(n-1)个盘子A–>B + 最大的盘子A–>c + (n-1)个盘子B–>C
看第一步,而如何将n-1个盘子从A移到B?思路也是一样的 ,由于第n个盘子比前n-1个盘子都要大,所以在这一层递归相当与没有
(n-2)个盘子A–>C + 最大的盘子A–>B + (n-2)个盘子C–>B
同理第三步:
(n-2)个盘子B–>A + 最大的盘子B–>C + (n-2)个盘子A–>C
以上的最大的盘子指的是要移动的x个盘子的最大的那个
所以整个过程就变成
- ((n-2)个盘子A->C+最大的盘子A–>B +(n-2)个盘子C–>B)+最大的盘子A–>c + ((n-2)个盘子B–>A
+最大的盘子B–>C + (n-2)个盘子A–>C)
如果令递归函数为fun(int n): 递归的式子就是:fun(n-1)+1+fun(n-1)
递归到只剩两个的时候只要移动三次就可以
int fun(int n)
{
if (n > 2)
return fun(n - 1) + 1 + fun(n - 1);
else
return 3;
}
进阶要求,要求打印出每一次移动的步骤:
思路:需要两个函数,一个用来打印步骤,一个用来完成递归
void move(char x,char y)
{
printf("%c到%c ", x, y);
}
void fun1(int n, char a, char b, char c)
{
if (n == 1)
{
move(a, c);
}
else
{
fun1(n - 1, a, c,b);
move(a, c);
fun1(n - 1, b, a,c);
}
}
青蛙跳台问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:
当青蛙遇到下次跳跃时会有两个选择:跳一个台阶,跳两个台阶,如果函数为fun()则返回为fun(n-1)+fun(n-2),当青蛙面前只有一个台阶的时候青蛙没有选择了,只能跳一个台阶,顾返回1
int fun(int n)
{
if (n > 1)
return fun(n - 1) + fun(n - 2);
else
return 1;
}