逛C++吧的時候看到一個人說看不懂漢諾塔遞歸算法,我去玩了下發現就是小時候學習機上的一個遊戲啊,那時候覺得相當有難度,4個就弄不出來了
之後仔細分析了一下,發現還挺有意思的。
先看看大致的步驟:
1個盤
1 a c
2個盤
1 a b
2 a c
1 b c
3個盤
1 a c
2 a b
1 c b
3 a c
1 b a
2 b c
1 a c
4個盤
1 a b
2 a c
1 b c
3 a b
1 c a
2 c b
1 a b
4 a c
1 b c
2 b a
1 c a
3 b c
1 a b
2 a c
1 b c
說明:編號爲
a爲左柱子,b爲中間柱子,c爲右柱子
目標是把所有盤移動到c位置,具體規則我就不細說了~
文字難以理解,我就多多上圖吧
分析:
電腦的計算力和記憶力超羣,但是智商低的可以,所以它只能看到事物表面,我們只需要告訴它有兩個盤的時候該怎麼做
那麼現在有4個盤,我們可以:
把1-3看成是一個盤,並且記住這個操作,那麼現在只有3,4兩個盤,電腦就知道該怎麼做了:
但是在進行第一步將3移動到中間柱子的時候,我們還需要進去,就像做夢中夢一樣,現在變成了:
目標變成了將3之上的所有盤移動到中間柱子,當然,在把2移動到借用位置的時候,我們還要進去......
以下省略XXX字,我們跳到最後一個
當只有最後一個的時候,我們就直接移動到目標位置咯(注意是目標位置,不是最右的柱子,每一步的目標都會改變,所以我們得根據上一層函數的指示移動),然後跳出
以下再省略XXX字......
在經過不斷進入和不斷出去之後(所以說電腦的記憶力超羣),我們所有的盤就都移動到最終目標了,下面上代碼:
#include <iostream>
using namespace std;
void move(int num,int loc_now,int loc_next,int loc_aim);
void move_cout(int num,int loc_now,int loc_next);
#define LOC_A 1 //初始位置
#define LOC_B 2 //借用位置
#define LOC_AIM 3 //目標位置
//每個位置的具體作用還要看具體情況,也許LOC_B是目標位置,LOC_AIM是借用位置,這是個宏觀的作用
int main()
{
int number;
cout<<"please input number"<<endl;
cin>>number;
move(number,LOC_A,LOC_B,LOC_AIM);
return 0;
}
/******************************************************
int num:此盤的編號
int loc_now:此盤現在所在的位置
int loc_use:將借用此位置移動到目標位置
int loc_aim:目標位置
*******************************************************/
void move(int num,int loc_now,int loc_use,int loc_aim)
{
if(num==1)//如果只剩最後一個,直接移動到目標位置
{
move_cout(num,loc_now,loc_aim);
}
else
{
move(num-1,loc_now,loc_aim,loc_use);//先把除了最下面那個盤移動到借用位置
move_cout(num,loc_now,loc_aim);//把最下面的盤移動到目標位置
move(num-1,loc_use,loc_now,loc_aim);//再把除了最下面那個盤移動到目標位置
}
}
/******************************************************
int num:此盤的編號
int loc_now:此盤現在所在的位置
int loc_next:將要移動到的位置
*******************************************************/
void move_cout(int num,int loc_now,int loc_next)
{
cout<<"num-"<<num<<" move from LOC_:"<<loc_now<<" to LOC_:"<<loc_next<<endl;
}
沒想到代碼這麼短,我們看下運行結果:
move(num-1,LOC_B,LOC_A,LOC_AIM);