分治與漢諾塔問題


分治與漢諾塔

 

 

分治算法

分治算法介紹

  1. 分治法是一種很重要的算法。字面上的解釋是“分而治之”,就是把一個復雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題……直到最后子問題可以簡單的直接求解,原問題的解即子問題的解的合並。這個技巧是很多高效算法的基礎,如排序算法(快速排序歸並排序),傅立葉變換(快速傅立葉變換)……
  2. 分治算法可以求解的一些經典問題
  • 二分搜索
  • 大整數乘法
  • 棋盤覆蓋
  • 合並排序
  • 快速排序
  • 線性時間選擇
  • 最接近點對問題
  • 循環賽日程表
  • 漢諾塔

 

分治算法的基本步驟

1.分治法在每一層遞歸上都有三個步驟:

2.分解:將原問題分解為若干個規模較小,相互獨立,與原問題形式相同的子問題

3.解決:若子問題規模較小而容易被解決則直接解,否則遞歸地解各個子問題

4.合並:將各個子問題的解合並為原問題的解。

 

分治(Divide-and-Conquer(P))算法設計模式如下

if |P|≤n0

   then return(ADHOC(P))

//將P分解為較小的子問題 P1 ,P2 ,…,Pk

for i←1 to k

do yi ← Divide-and-Conquer(Pi)   遞歸解決Pi

T ← MERGE(y1,y2,…,yk)   合並子問題

return(T)

其中|P|表示問題P的規模;n0為一閾值,表示當問題P的規模不超過n0時,問題已容易直接解出,不必再繼續分解。ADHOC(P)是該分治法中的基本子算法,用於直接解小規模的問題P。因此,當P的規模不超過n0時直接用算法ADHOC(P)求解。算法MERGE(y1,y2,…,yk)是該分治法中的合並子算法,用於將P的子問題P1 ,P2 ,…,Pk的相應的解y1,y2,…,yk合並為P的解。

 

 

分治算法最佳實踐-漢諾塔

  • 漢諾塔的傳說

漢諾塔:漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵

天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。

假如每秒鍾一次,共需多長時間呢?移完這些金片需要5845.54億年以上,太陽系的預期壽命據說也就是數百億年。真的過了5845.54億年,地球上的一切生命,連同梵塔、廟宇等,都早已經灰飛煙滅。

 

 

 

 

 

分治算法最佳實踐-漢諾塔

漢諾塔游戲的演示和思路分析:   

  1. 如果是有一個盤, A->C

如果我們有 n >= 2 情況,我們總是可以看做是兩個盤 1.最下邊的盤 2. 上面的盤

1. 先把 最上面的盤 A->B  移動過程會使用到 c

  1. hanoiTower(num - 1, a, c, b);

3. 把最下邊的盤 A->C

  1. System.out.println("第" + num + "個盤從 " + a + "->" + c);

5. B塔的所有盤 從 B->C    移動過程會使用到 b 

  1. hanoiTower(num - 1, b, a, c);

 

 

完整代碼

package com.atguigu.dac;

public class Hanoitower {

        public static void main(String[] args) {
                hanoiTower(10, 'A', 'B', 'C');
        }
        
        //漢諾塔的移動的方法
        //使用分治算法
        
        public static void hanoiTower(int num, char a, char b, char c) {
                //如果只有一個盤
                if(num == 1) {
                        System.out.println("第1個盤從 " + a + "->" + c);
                } else {
                        //如果我們有 n >= 2 情況,我們總是可以看做是兩個盤 1.最下邊的一個盤 2. 上面的所有盤
                        //1. 先把 最上面的所有盤 A->B, 移動過程會使用到 c
                        hanoiTower(num - 1, a, c, b);
                        //2. 把最下邊的盤 A->C
                        System.out.println("第" + num + "個盤從 " + a + "->" + c);
                        //3. 把B塔的所有盤 從 B->C , 移動過程使用到 a塔  
                        hanoiTower(num - 1, b, a, c);
                        
                }
        }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM