今天為大家講一道非常有趣的問題,hanoi塔問題,相信很多同學都曾經玩過這個游戲,今天我們嘗試着靠編程來解決它
題目描述
A、B、C 是3個塔座。開始時,在塔座A 上有一疊共n 個圓盤,這些圓盤自下而上,由大到小地疊在一起。各圓盤從小到大編號為1,2,……,n,奇數號圓盤着藍色,偶數號圓盤着紅色,如圖所示。現要求將塔座A 上的這一疊圓盤移到塔座B 上,並仍按同樣順序疊置。在移動圓盤時應遵守以下移動規則:
規則(1):每次只能移動1個圓盤;
規則(2):任何時刻都不允許將較大的圓盤壓在較小的圓盤之上;
規則(3):任何時刻都不允許將同色圓盤疊在一起;
規則(4):在滿足移動規則(1)-(3)的前提下,可將圓盤移至A,B,C 中任一塔座上。
試設計一個算法,用最少的移動次數將塔座A 上的n個圓盤移到塔座B 上,並仍按同樣順序疊置。
編程任務:
對於給定的正整數n,編程計算最優移動方案。
規則(1):每次只能移動1個圓盤;
規則(2):任何時刻都不允許將較大的圓盤壓在較小的圓盤之上;
規則(3):任何時刻都不允許將同色圓盤疊在一起;
規則(4):在滿足移動規則(1)-(3)的前提下,可將圓盤移至A,B,C 中任一塔座上。
試設計一個算法,用最少的移動次數將塔座A 上的n個圓盤移到塔座B 上,並仍按同樣順序疊置。

編程任務:
對於給定的正整數n,編程計算最優移動方案。
輸入
輸入由多組測試數據組成。每組測試數據的第1 行是給定的正整數n。
輸出
對應每組輸入,輸出的每一行由一個正整數k和2 個字符c1 和c2 組成,表示將第k 個圓盤從塔座c1 移到塔座c2 上。
樣例輸入 Copy
3
樣例輸出 Copy
1 A B 2 A C 1 B C 3 A B 1 C A 2 C B 1 A B
提示
考察一個普通的漢諾塔問題,如果按照最少步驟移動(即沒有無意義的移來移去):
普通的漢諾塔(把盤子1~k由source移動到target)問題分三個階段
1.把盤子1~ k-1由source(k上面)移動到assistant
2.把盤子k由source移動到target
3.把盤子1~ k-1由assistant移動到target(k上面)
在這里我們把盤子1~ k-1的移動看做一個整體進行移動
那么假設存在一個違反雙色規則移動的盤子m-1,它放在了盤子m+1上,但是你讓盤子m怎么辦呢?在移動1~m+1這個層次並沒有盤子m在m+1所在柱子之外的兩個柱子間移動的步驟。
m-1放在m+3、m+5、m+7……之上也是不可能的,因為同樣地,就拿m+3來說,在移動1~m+3這個層次沒有盤子m+2在m+3所在柱子之外的兩個柱子間移動的步驟。
所以這種違規必然是一個多余的操作,違規地移動之后,必須要移下來才能正常繼續。
普通的漢諾塔(把盤子1~k由source移動到target)問題分三個階段
1.把盤子1~ k-1由source(k上面)移動到assistant
2.把盤子k由source移動到target
3.把盤子1~ k-1由assistant移動到target(k上面)
在這里我們把盤子1~ k-1的移動看做一個整體進行移動
那么假設存在一個違反雙色規則移動的盤子m-1,它放在了盤子m+1上,但是你讓盤子m怎么辦呢?在移動1~m+1這個層次並沒有盤子m在m+1所在柱子之外的兩個柱子間移動的步驟。
m-1放在m+3、m+5、m+7……之上也是不可能的,因為同樣地,就拿m+3來說,在移動1~m+3這個層次沒有盤子m+2在m+3所在柱子之外的兩個柱子間移動的步驟。
所以這種違規必然是一個多余的操作,違規地移動之后,必須要移下來才能正常繼續。
題解代碼:
#include<iostream>
#include<string>
using namespace std;
int n;
void hanoi(int k,char from,char assistant,char to){
if(k==1){
printf("%d %c %c\n",1,from,to);
return ;
}
else{
hanoi(k-1,from,to,assistant);
printf("%d %c %c\n",k,from,to);
hanoi(k-1,assistant,from,to);
}
}
int main(){
scanf("%d",&n);
hanoi(n,'A','C','B');
return 0;
}
#include<string>
using namespace std;
int n;
void hanoi(int k,char from,char assistant,char to){
if(k==1){
printf("%d %c %c\n",1,from,to);
return ;
}
else{
hanoi(k-1,from,to,assistant);
printf("%d %c %c\n",k,from,to);
hanoi(k-1,assistant,from,to);
}
}
int main(){
scanf("%d",&n);
hanoi(n,'A','C','B');
return 0;
}
題解思路:
這道題的思路我們通過第一次遞歸hanoi(n,A,C,B)來講解,在將A底下最大的n的移到目的B柱之前,需要先將A柱上的1到n-1個環通過B移到C上,
我們可以利用第二次遞歸hanoi(n-1,A,B,C)來運算;在將A底下最大的n的移到目的B柱之后,我們便要將C上的1到n-1個環通過A柱移到B柱上,利用遞歸
hanoi(n-1,C,A,B)實現,每次遞歸只能移一個,搞清楚起始柱from,中間柱(協助作用)assistant和目的柱to的關系,即將最大的n由from移到to之前,需要將1到
n-1移到assistant上;移完后需將assistant的1到n-1再通過from移到to上來