來源及應用
相傳在古印度圣廟中,有一種被稱為漢諾塔(Hanoi)的游戲。該游戲是在一塊銅板裝置上,有三根桿(編號A、B、C),在A桿自下而上、由大到小按順序放置64個金盤(如圖1)。游戲的目標:把A桿上的金盤全部移到C桿上,并仍保持原有順序疊好。操作規則:每次只能移動一個盤子,并且在移動過程中三根桿上都始終保持大盤在下,小盤在上,操作過程中盤子可以置于A、B、C任一桿上。
? ? ? 分析:對于這樣一個問題,任何人都不可能直接寫出移動盤子的每一步,但我們可以利用下面的方法來解決。設移動盤子數為n,為了將這n個盤子從A桿移動到C桿,可以做以下三步:
(1)以C盤為中介,從A桿將1至n-1號盤移至B桿;
(2)將A桿中剩下的第n號盤移至C桿;
(3)以A桿為中介;從B桿將1至n-1號盤移至C桿。
?
漢諾塔(Tower of Hanoi),又稱河內塔,是一個源于印度古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
2020年8月3日,夏焱以33.039秒的成績成功打破6層漢諾塔吉尼斯世界紀錄。?[5-7]
2021年5月16日,中國龍巖的陳諾以29.328秒的成績打破了6層漢諾塔吉尼斯世界紀錄。?[8]
?
問題解讀:
?簡而言之,這里有三個桿,上面串了n個大小不同的盤,需要將這n個盤經過這三個桿,將全部盤轉移到另一個桿上,并且這三個桿在轉移的過程中,都要滿足桿上的盤要由大到小進行排列。
過程分析
當n等于1時:
只需要挪動一次就好了。
當n等于2時:
仔細思考,不難想到:會經過三個步驟 。
1.A->B
2.A->C
3.B->C
?
?當n等于3時:
同樣的道理,我們需要間接的利用這三個桿完成盤子的轉移。
?
1.A->C,A->B:
?
?2.C->B,A->C
4.B->A,B->C,A->C
?最終完成了當n等于3的情況,一共挪動了7步。
解題思路:
通過我們上面對n的分析,我們知道當n等于1時,挪1步,當n等于2時挪3步,當n等于3時,挪動7步,仔細觀察不難找到這樣一個規律:挪的步數=2^x-1.這樣我們就找到了這個問題的突破口。
? ?我們根據n的取值可以將他分為:
具體可以參考當n等于3時進行深入理解。?
代碼實現:
經過上面的分析,我們就可以利用java中的遞歸方法來完成漢諾塔問題,如果你對遞歸有問題的話,可以看一下我的上一篇文章,里面詳細介紹了遞歸的知識,具體實現的時候,利用的就是我們上面找到的規律:
話不多說,直接上代碼:
public class Main {public static void move(char pos1,char pos2){System.out.print(pos1+"->"+pos2+" ");}public static void hanio(int n,char pos1,char pos2,char pos3){if(n==1){move(pos1,pos3);}else{hanio(n-1,pos1,pos3,pos2);move(pos1,pos3);hanio(n-1,pos2,pos1,pos3);}}public static void main(String[] args) {hanio(1,'A','B','C');System.out.println();hanio(2,'A','B','C');System.out.println();hanio(3,'A','B','C');System.out.println();hanio(4,'A','B','C');}
}
好了,今天就分享這么多,謝謝大家。