2020-09-1310:42:28
@
19世纪的时候,法国数学家爱德华·卢卡斯创造了一个叫汉诺塔的神话:佛教大神梵天在创造世界的时候有点无聊,顺便造了三根金刚石柱子,其中第一根柱子上堆了64块黄金圆盘。梵天命令僧侣把所有圆盘从第一根柱子移动到第三根柱子上,且每次只能移动一片,小圆盘必须在大圆盘的上面。
梵天对僧侣说,如果全部把圆盘搬完,世界将会毁灭,所有的佛塔、庙宇、僧侣都将在烈火中化为灰烬。
僧侣搬完所有圆盘,需要多长时间?这个问题可以用递归算法来求解。
递归
递归算法在程序设计中被广泛应用。根据度娘的解释,递归,就是函数直接或间接地调用函数自身,直到引用对象可知。(有点像现在流行的“套娃”梗)
递归有一个好处,就是可以把复杂的步骤简化成几个简单的步骤,从而实现对复杂问题的一步步拆解。
比如,在汉诺塔游戏中,要把n个圆盘按上述规则从A柱子移动到C柱子上,我们可以按三个大步骤去做:
1、先把上面的n-1个圆盘移动到B柱子;
2、把第n个(即最底层的那个)圆盘移动到C柱子;
3、最后把n-1个圆盘从B柱子移动到C柱子,就完成了。
而回到第一个步骤,怎么把n-1个圆盘按规则移动到B柱子上呢?可以继续进行拆解,先把n-2个圆盘移动到C柱子上,然后把第n-1个圆盘移动到B柱子上,最后把n-2个圆盘从C柱子移动到B柱子……
这样一直拆解下去,最终就可以分解为每次只移动一个圆盘的步骤了。
拆解的流程如下:
于是,就有这样的结论:
回到最初的问题,如果僧侣需要把64个圆盘从第一根柱子移动到第三根柱子,需要搬动(2^64-1)次,假设每秒钟搬动一次,共需要5800亿年。
1 /*汉诺塔递归算法*/ 2 #include <stdio.h> 3 void move(int n,char x,char y) 4 { 5 printf("%c-->%c ",x,y); 6 } 7 void hanota(int n,char A,char B,char C) 8 //一共n个盘子,要把这n个盘子借助B柱子从A柱子全部移到C柱子 9 { 10 if(n==1)//递归出口,也就是结束的标志 11 { 12 move(n,A,C);//当只有一个盘子的时候,直接从A柱子移到C柱子 13 } 14 else 15 { 16 hanota(n-1,A,C,B);//当n>1时,把(n-1)个盘子借助C柱子从A柱子移到B柱子 17 move(n,A,C);//然后把第n个盘子从A柱子移到C柱子 18 hanota(n-1,B,A,C);//再把(n-1)个盘子借助A柱子从B柱子移到C柱子 19 } 20 } 21 //主函数 22 int main() 23 { 24 int m; 25 char a='A',b='B',c='C'; 26 scanf("%d",&m);//输入有几个盘子 27 hanota(m,a,b,c); 28 return 0; 29 }