歡迎前往個人博客 駑馬點滴 和視頻空間 嗶哩嗶哩-《挨踢日志》
【問題】
a,b,c是三個塔座。開始時,在a上共有n個圓盤,自上而下,圓盤由小到大。編號分別為1,2,...,n. 現在要通過b塔把圓盤從a塔移動到c塔.試寫出移動過程hanoi(n,a,b,c).
【解答】
建模
我們記錄每一次轉移為 x -> y 其中 x~=y, x, y從{a, b, c}中取值
那么問題就是要給出一些列的轉移的有序集合,使得按照集合中的步驟,能夠將n個盤從a移動到c
這里有3個塔: a、b、c,由于a是起始塔,而c是目標塔,b就是輔助塔,于是需要引入3個變量:起始塔、目標塔、輔助塔
同時還有一個由圓盤組成的堆的概念。有一個變量n用于描述這個堆的大小,因為我們不希望打亂堆的從上到下的圓盤是由小到大的布局,所以,n就唯一決定了這個堆的特性。
顯然,我們接觸到n這個變量,自然希望使用數學歸納法來解決這樣的問題,于是問題,應當考慮將n的情形轉化為n-1的情形,從而通過遞歸完成我們的解決方案。
首先我們假定解決方案是一個關于 n 和 起始塔、輔助塔、目標塔 的函數 hanoi(n, 起始塔, 輔助塔, 目標塔)
表示n個圓盤,從起始塔,通過輔助塔移動到目標塔的解決方案。
那么我們需要求解的問題就是:hanoi(n, a, b, c)
而 hanoi(n, a, b, c)的解決方案是一個步驟方案,于是我們又可以將這個過程視為3大步驟:
- 先將a上面的n-1個盤組成的堆從a,借助輔助塔c,轉移到b的解決方案hanoi(n-1, a, c, b)
- 將第n個盤移動到c: hanoi(1, a, b, c)
- 再將b上面的n-1個盤組成的堆從b,借助輔助塔a,轉移到c的解決方案hanoi(n-1, b, a, c)
于是遞歸算法如下:
void LankeHelper::hanoi(int n, char a, char b, char c){
if(n==1)
{
cout<<a<<"->"<<c<<"\n";
}
else {
hanoi(n-1,a,c,b);
hanoi(1, a, b, c);
hanoi(n-1,b,a,c);
}
}
int _tmain(int argc, _TCHAR* argv[]){
LankeHelper lh;
lh.hanoi(2,'a','b','c');
system("pause");
return 0;
}
歡迎前往個人博客 駑馬點滴 和視頻空間 嗶哩嗶哩-《挨踢日志》