4柱漢諾塔(zz)


多柱漢諾塔可以用Frame–Stewart算法來解決。

The Frame–Stewart algorithm, giving a presumably optimal solution for four (or even more) pegs, is described below:

  • Let n be the number of disks.
  • Let r be the number of pegs.
  • Define T(n,r) to be the minimum number of moves required to transfer n disks using r pegs

The algorithm can be described recursively:

  1. For some k, 1 \leq k < n, transfer the top k disks to a single peg other than the start or destination pegs, taking T(k,r) moves.
  2. Without disturbing the peg that now contains the top k disks, transfer the remaining n-k disks to the destination peg, using only the remaining r-1 pegs, taking T(n-k,r-1) moves.
  3. Finally, transfer the top k disks to the destination peg, taking T(k,r) moves.

The entire process takes 2T(k,r)+T(n-k,r-1) moves. Therefore, the count k should be picked for which this quantity is minimum.

This algorithm (with the above choice for k) is presumed to be optimal, and no counterexamples are known.

4柱的可以借助3柱的來完成,5柱的借助4柱的來完成,等等。下面是從網上找來的4柱漢諾塔的分析過程。

 

四塔問題:設有A,B,C,D四個柱子(有時稱塔),在A柱上有由小到大堆放的n個盤子,如圖所示。

今將A柱上的盤子移動到D柱上去。可以利用B,C柱作為工作棧用,移動的規則如下:
①每次只能移動一個盤子。
②在移動的過程中,小盤子只能放到大盤子的上面。
設計並實現一個求解四塔問題的動態規划算法,並分析時間和空間復雜性。
 
算法思想:
用如下算法移動盤子(記為FourPegsHanoi):
1)、將A柱上n個盤子划分為上下兩部分,下方部分共有k(1≤k≤n)個盤子,上方部分共有n - k個盤子。
2)、將A柱上面部分n–k個盤子使用FourPegsHanoi算法經過C、D柱移至B柱。
3)、將A柱剩余的k個盤子使用ThreePegsHanoi算法經過C柱移至D柱。
4)、將B柱上的n–k個盤子使用FourPegsHanoi算法經過A、C柱移至D柱。
 
ThreePegsHanoi算法如下(設三個柱子分別為A、B、C,A柱上共有k個盤子):
1)、將A柱上方k-1個盤子使用ThreePegsHanoi算法經過B柱移至C柱。
2)、將C柱上最后一個盤子直接移至C盤。
3)、將B柱上k-1個盤子使用ThreePegsHanoi算法經過A柱移至C柱。

 

算法步驟:
根據動態規划的四個步驟,求解如下:
1)、最優子結構性質:
   四柱漢諾塔問題的最優解是用最少的移動次數將A柱上的盤子全部移到D柱上。當盤子總數為i時,我們不妨設使用FourPegsHanoi的最少移動次數為f(i)。相應的ThreePegsHanoi 算法移動次數為g(k),由於g(k)=2g(k-1)+1=2k -1,當k確定時,g(k)也是不變的。
   f(i)為最優解時,其子問題f(i-k)也必為最優解。如果f(i-k)不是最優解,那么存在f’(i-k) < f(i-k)。用f’(i-k)替換f(i-k)將產生一個比f(i)更優的解。這與f(i)為最優解是矛盾的。所以本問題具有最優子結構性質。

2)、遞歸地定義問題的最優解:
根據上述FourPegsHanoi算法得到最少移動次數f(i):


image

通過這個表達式我們可以知道,k取那個值時f(i)的值,也就是說,不用具體操作,就可以知道移動的最少次數,並且知道k的值,所以在算法實現時,求出k的值是非常重要的。下面的代碼就是用來求k的。

 

int FourPegHanoi::minMoves()
{
        int min = - 1;
        moves[ 0][ 0] = 0;
        splitter[ 0] = 0;
        for( int i = 1;i<= m_Plates;i++)
        {
                min = 1000000000;
                for( int j= 1;j<=i;j++)
                {
                        moves[i][j] = 2*moves[i-j][splitter[i-j]] - 1 + ( 2<<(j- 1)) ;
                        if(moves[i][j] < min)
                        {
                                min = moves[i][j];
                                splitter[i] = j;
                        }
                }
        }
        for( int i= 1;i<=m_Plates;i++)
                cout<<splitter[i]<<endl;

        return moves[m_Plates][splitter[m_Plates]];
}

時間空間復雜度分析:
1、時間復雜度
MinMovements算法的時間復雜度為:
T(n) = 1 + 2 + ... + n = n(n+1)/2 = O(n2)
2、空間復雜度
MinMovements算法占用的空間為m 和 s數組的大小:
即 (n+1)2 + (n+1) = O(n2)
通過分析m數組中記錄了一些與結果不相關的數據,所以通過對MinMovements進行改進,可使占用空間減小為O(n)。


免責聲明!

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



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