多柱漢諾塔可以用Frame–Stewart算法來解決。
The Frame–Stewart algorithm, giving a presumably optimal solution for four (or even more) pegs, is described below:
- Let
be the number of disks.
- Let
be the number of pegs.
- Define
to be the minimum number of moves required to transfer n disks using r pegs
The algorithm can be described recursively:
- For some
,
, transfer the top
disks to a single peg other than the start or destination pegs, taking
moves.
- Without disturbing the peg that now contains the top
disks, transfer the remaining
disks to the destination peg, using only the remaining
pegs, taking
moves.
- Finally, transfer the top
disks to the destination peg, taking
moves.
The entire process takes moves. Therefore, the count
should be picked for which this quantity is minimum.
This algorithm (with the above choice for ) 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):
通過這個表達式我們可以知道,k取那個值時f(i)的值,也就是說,不用具體操作,就可以知道移動的最少次數,並且知道k的值,所以在算法實現時,求出k的值是非常重要的。下面的代碼就是用來求k的。
{
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)。