算法經典趣題:漢諾塔(Hanoi)問題

漢諾塔算法

漢諾塔問題時一個典型的遞歸算法問題,可以先從簡單的3層漢諾塔入手。假設有ABC三根棒子,初始狀態時,A棒上放着3個圓盤,將其移動到C棒上,可以用B棒暫時放置圓盤。並且規定一次只能移動一個圓盤,且圓盤在放到棒上時,大的只能放在小的下面。

使用遞歸思想,可以採用以下步驟來完成圓盤的移動:

(1)將A棒上的兩個圓盤(圓盤1和圓盤2)移到B棒上;

(2)將A棒上剩下的一個圓盤移到C棒上;

(3)將B棒上的兩個圓盤(圓盤1和圓盤2)移到C棒上,即移動完成。

這裏第一步和第三步是移動多個圓盤的操作,可以採用遞歸的思想,仍然使用上述步驟來完成。

將上述解決問題的步驟加以推廣,便可得到如下遞歸求解漢諾塔算法:

如果只有一個圓盤,則把該圓盤從A棒移動到C棒,完成移動。如果圓盤數量 n>1,移動圓盤的過程可分爲三步:

(1)將A棒上的n-1個圓盤移到B棒上;

(2)將A棒上的1個圓盤移到C棒上;

(3)將B棒上的n-1個圓盤移到C棒上。

其中,移動n-1個圓盤的工作可以歸結爲遞歸運算。

    void hanoi(int n,char a,char b,char c){
        // 只有一個盤子的時候,從A棒移動到C棒即可
        if(n == 1){
            System.out.printf("第%d次移動:圓盤從%c棒移動到%c棒%n",++count,a,c);
        }else{
            // 當有n個盤子時,將n-1個盤子先從A棒上移到緩衝B棒上
            // 把A棒上剩下的1個圓盤移到終點C棒上
            // 然後再將這n-1個盤子從緩衝b棒上移到終點C棒上
            hanoi(n-1,a,c,b);
            hanoi(1,a,b,c);
            hanoi(n-1,b,a,c);
        }
    }

漢諾塔求解

public class HanoiTower {
    // 漢諾塔——典型的遞歸算法問題
    private static int count = 0;
    // n爲盤子數量,a爲起點,b爲緩衝,c爲終點
    public static void hanoi(int n,char a,char b,char c){
        // 只有一個盤子的時候,從A棒移動到C棒即可
        if(n == 1){
            System.out.printf("第%d次移動:圓盤從%c棒移動到%c棒%n",++count,a,c);
        }else{
            // 當有n個盤子時,將n-1個盤子先從A棒上移到緩衝B棒上
            // 把A棒上剩下的1個圓盤移到終點C棒上
            // 然後再將這n-1個盤子從緩衝b棒上移到終點C棒上
            hanoi(n-1,a,c,b);
            hanoi(1,a,b,c);
            hanoi(n-1,b,a,c);
        }
    }

    public static void main(String[] args) {
        System.out.println("***漢諾塔問題求解***");
        System.out.println("請輸入漢諾塔圓盤的數量:");
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        hanoi(n,'A','B','C');
        System.out.printf("求解完畢,總共需要%d步移動!",count);
    }
}

運行代碼結果如下:

***漢諾塔問題求解***
請輸入漢諾塔圓盤的數量:
3
第1次移動:圓盤從A棒移動到C棒
第2次移動:圓盤從A棒移動到B棒
第3次移動:圓盤從C棒移動到B棒
第4次移動:圓盤從A棒移動到C棒
第5次移動:圓盤從B棒移動到A棒
第6次移動:圓盤從B棒移動到C棒
第7次移動:圓盤從A棒移動到C棒
求解完畢,總共需要7步移動!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章