【每週一算】漢諾塔(河內塔)

(來自百度百科)一位法國數學家曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裏,一塊黃銅板上插着三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消滅,而梵塔、廟宇和衆生也都將同歸於盡。

不管這個傳說的可信度有多大,如果考慮一下把64片金片,由一根針上移到另一根針上,並且始終保持上小下大的順序。這需要多少次移動呢?這裏需要遞歸的方法。假設有n片,移動次數是f(n).顯然f⑴=1,f⑵=3,f⑶=7,且f(k+1)=2*f(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億年,不說太陽系和銀河系,至少地球上的一切生命,連同梵塔、廟宇等,都早已經灰飛煙滅。

背景說完了,看下java實現吧。

package com.jandmin.demo.leetcode;

/**
 * 漢諾塔
 *      就是在一塊木板上有三個立柱,在柱1上放着三個圓盤,小的在上面,大的在下面(初始狀態)。
 *      將在柱1上的三個圓盤移到柱3上面(目標狀態)。
 *      條件是:每次只能移動任何一個柱子上面的一個圓盤,但大的圓盤不能放在小的圓盤上。
 * @author: JandMin
 * @create: 2019-06-06 09:38
 **/
public class TowerOfHanoi {
    public static void main(String[] args) {
        // 假設3個柱子分別位 A B C,圓盤初始放在A柱上,移動C柱
        char pillar1 = 'A';
        char pillar2 = 'B';
        char pillar3 = 'C';
        // 初始圓盤數量
        int count = 4;
        move(count,pillar1,pillar2,pillar3);
    }

    /**
     * @Description: 移動圓盤
     * @Date: 2019/6/13
     * @param count 總的圓盤數量
     * @param from 第一個柱子
     * @param middle 第二個柱子
     * @param to 第三個柱子
     * @return: void
     */
    private static void move(int count, char from, char middle, char to) {
        if(count < 1){
            System.out.println("輸入有誤");
            return;
        }
        if(1 == count){
            print(count,from,to);
        } else {
            move(count-1,from,to,middle);// 2、把第n-1個盤子從 開始柱子 移到 中間柱子
            print(count,from,to);        // 1、把當前盤子從    開始柱子 移到 目標柱子
            move(count-1,middle,from,to);// 3、把第n-1個盤子從 中間柱子 移到 目標柱子
        }
    }

    /**
     * @Description: 打印移動過程
     * @Date: 2019/6/13
     * @param num 第幾個圓盤
     * @param from
     * @param to
     * @return: void
     */
    private static void print(int num, char from, char to) {
        System.out.println("第 " + num + " 個圓盤: " + from + " ---> " + to);
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章