码迷,mamicode.com
首页 > 其他好文 > 详细

河内塔

时间:2014-12-17 23:57:58      阅读:516      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   ar   io   color   sp   strong   on   

 

一、 河内塔的起源

 
1883年,一位法国的数学家Edouard Lucas 教授在欧洲的一份杂志上介绍了一个相当吸引人的难题──迷人的智力游戏。 这个游戏名为河内塔(Tower of Hanoi),它源自古印度神庙中的一段故事(也有一说是Lucas 教授为增加此游戏之神秘色彩而捏造的)。 传说在古老的印度,有一座神庙,据说它是宇宙的中心。 在庙宇中放置了一块上面插有三根长木钉的木板,在其中的一根木钉上,从上至下被放置了64片直径由小至大的圆环形金属片。 古印度教的天神指示祂的僧侣们将64片的金属片移至三根木钉中的其中一根上。 规定在每次的移动中,只能搬移一片金属片,并且在过程中必须保持金属片由上至下是直径由小至大的次序,也就是说不论在那一根木钉上,圆环形的金属片都是直径较小的被放在上层。 直到有一天,僧侣们能将64片的金属片依规则从指定的木钉上全部移动至另一根木钉上,那么,世界末日即随之来到,世间的一切终将被毁灭,万物都将至极乐世界。
 
倘若这个故事的叙述为真,那么,我们只需加速移动金属片,是不是就能愈早到达极乐世界呢? 果真要移动这64片金属片,那么,至少要花几次的搬动才能完成呢? 有没有规律可循呢?
 

二、 河内塔的数学

对于河内塔游戏也可以经由数学上的方法得到一些漂亮的结果:若一开始就考虑64片金属片似乎太难了,我们不妨把金属片的数量降低至2片,看看会有什么结果?

如果只有1片,显然只须移动一次即可。 当2片直径不一的金属片放在同一木钉上,必须将最上的那一片先移至非指定的木钉上,然后将第二片金属片移至指定的木钉上,再接着将第一片金属片移至第二片之上,所以,至少要花3次搬移来完成。 若是3片金属片,依相同的讨论方法,可得知须至少移动金属片7次,如图1。
 
 
bubuko.com,布布扣
      图 1
 
 
那当n很大时(金属片数= n ),至少要花几次呢?
      现在假设至少须T(n) 次的移动来完成,那么,我们再加一片金属片,即此时共有n+1 片金属片;我们知道前n 片花了T(n) 次来移动至另一根木钉上,第n+1 片金属片只须花一次就可移至指定的木钉上,所以,只须再花T(n) 次的移动将n 片金属片移至这一片金属片之上,这就完成了任务──有n+1 片金属片移到另一根木钉上。 它们都是在规范内被完成移动,所以最少移动次数有如下迭代公式:
 
T(n+1) = 2T(n) + 1
 
又已知T(1) = 1, T(2) = 3, T(3) = 7 ,因此是否可以推出T(64)?
由迭代公式知道:
T(n+1) = 2T(n) + 1
T(n+1)+ 1 = 2T(n) + 2
T(n+1) + 1 = 2(T(n) + 1) 
 
因此构造出以公比为2的等比数列,不难计算知道的公式为:
 

bubuko.com,布布扣

     所以我们可以计算出:bubuko.com,布布扣
 
好了,河内塔的数学推导暂时到这里了,现在我们看看它何如在三个柱子之间移动的。

四、 河内塔移动方式

若将三根木钉排成一个三角形(即木钉在三角形的顶点)如图2。 假设,移动金属片的方式被分为顺时针方向及逆时针方向,每做一次顺时针方向移动,我们在纸上划上﹨,做一次逆时针方向则划上∕,若令出发点为A 柱,终点为C 柱。 逐步记录结果:
 
 
bubuko.com,布布扣
 
 
    图 2
 
三片金属片移动的路径:
                     bubuko.com,布布扣
 
 
 

5、汉诺塔移动路径实现算法(摘自百度百科,链接:http://baike.baidu.com/view/191666.htm#4_3):

   算法介绍

其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n – 1(有兴趣的可以自己证明试试看)。后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C;
若n为奇数,按顺时针方向依次摆放 A C B。
⑴按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。
⑵接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。
⑶反复进行⑴⑵操作,最后就能按规定完成汉诺塔的移动。
所以结果非常简单,就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
现在我给出我自己写的C语言代码:
 1 #include <stdio.h>
 2 
 3 //A桩为初始位置,B为临时位置,C为目的位置,n为现在A桩上盘子的数目 
 4 void Hanoi_towers(char A, char B, char C, int n) 
 5 {
 6     if( n == 1)
 7         printf("%c===>%c\n", A, C);  /**
 8                                       *因为在只有一片金属片时, 
 9                                       *直接将A移动到C既可 */
10     else{
11         Hanoi_towers(A, C, B, n - 1); /**
12                                        *当金属片只有大于一片时,
13                                        *借助B作临时存放A的位置 */
14         printf("%c===>%c\n", A, C);   //因为移动了一次,则将其输出 
15         Hanoi_towers(B, A, C, n - 1);  /**
16                                         *因为借助了B为临时存放A,
17                                         *最后要将其A归回原位*/
18     } 
19 }
20 
21 int main()
22 {
23     Hanoi_towers(A,B,C,3);
24     return 0;
25 }
内容参考源于:http://www.chiuchang.com.tw/toy/hanoi/hanoi.html

河内塔

标签:style   blog   http   ar   io   color   sp   strong   on   

原文地址:http://www.cnblogs.com/John-Deng/p/4170648.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!