汉诺塔学习,今天终于搞懂了汉诺塔的实现过程,说起来很麻烦,但是实现真的递归一下就是很简单的事了。
在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石
针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所
谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针
上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就
将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=
3,f(3)=7,且f(k+1)=2*f(k)+1 (f(k+1)可以理解为现将k个金片全部移动到第三个针上面,然后再将最后的第k+1
个金块放到第二个针上面,然后再次利用三根针将三针上面的金片移动到二针上面),有递归表达式可以求得f(n)
=2^n-1
n=64时,
f(64)= 2^64-1=18446744073709551615
假如每秒钟一次
,共需多长时间呢?一个平年365天有 31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下,
18446744073709551615/31556952=584554049253.855年
这表明移完这些金片需要5845亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。
真的过了5845亿年,不说太阳系和银河系,至少地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭.
先我们肯定是把上面n-1个盘子移动到柱子C上,然后把最大的一块放在B上,最后把C上的所有盘子移动到B上,
由此我们得出表达式:
H(1) = 1
H(n) = 2*H(n-1)+1 (n>1)
public static void move(int number,int fromtower,int totower,int auxtower){
if(number==1)
System.out.println("Move disk 1 from the "+fromtower+" to the "+totower);
else{
move(number-1,fromtower,auxtower,totower);
System.out.println("Move disk "+number+" from the "+fromtower+" to the "+totower);
move(number-1, auxtower, totower, fromtower);
}
move(int num, int fromtower, int totower, int auxtower),是进行move的函数,可以这样理解为将num个盘子
auxtower,从fromtower移动到totower,然后拆分问题,进行到将n-1个盘子从fromtower移动到totower,经过auxtower
的辅助,然后将最后一个盘子移到totower上面,最后再将auxtower上面的盘子全部移动到totower上面借助于fromtower。
在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石
针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所
谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针
上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就
将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=
3,f(3)=7,且f(k+1)=2*f(k)+1 (f(k+1)可以理解为现将k个金片全部移动到第三个针上面,然后再将最后的第k+1
个金块放到第二个针上面,然后再次利用三根针将三针上面的金片移动到二针上面),有递归表达式可以求得f(n)
=2^n-1
n=64时,
f(64)= 2^64-1=18446744073709551615
假如每秒钟一次
#include <stdio.h>
void move(int n, int fromtower, int midtower, int totower)
{
if (n == 1)
{
printf("step %d: move disk 1 from tower %d to tower %d.\n", count++, fromtower, totower);
}
else
{
move(n-1, fromtower, midtower, totower);
printf("step %d: move disk %d from tower %d to tower %d.\n", count++, n, fromtower, totower);
move(n-1, midtower, totower, fromtower);
}
}
int main()
{
int n;
printf("Please input the number of disks:\n");
scanf("%d", &n);
move(n, 1, 3, 2);
return 0;
}
,共需多长时间呢?一个平年365天有 31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下,
18446744073709551615/31556952=584554049253.855年
这表明移完这些金片需要5845亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。
真的过了5845亿年,不说太阳系和银河系,至少地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭.
先我们肯定是把上面n-1个盘子移动到柱子C上,然后把最大的一块放在B上,最后把C上的所有盘子移动到B上,
由此我们得出表达式:
H(1) = 1
H(n) = 2*H(n-1)+1 (n>1)
public static void move(int number,int fromtower,int totower,int auxtower){
if(number==1)
System.out.println("Move disk 1 from the "+fromtower+" to the "+totower);
else{
move(number-1,fromtower,auxtower,totower);
System.out.println("Move disk "+number+" from the "+fromtower+" to the "+totower);
move(number-1, auxtower, totower, fromtower);
}
move(int num, int fromtower, int totower, int auxtower),是进行move的函数,可以这样理解为将num个盘子
auxtower,从fromtower移动到totower,然后拆分问题,进行到将n-1个盘子从fromtower移动到totower,经过auxtower
的辅助,然后将最后一个盘子移到totower上面,最后再将auxtower上面的盘子全部移动到totower上面借助于fromtower。