【題目描述】
約19世紀末,在歐州的商店中出售一種智力玩具,在一塊銅板上有三根杆,最左邊的杆上自上而下、由小到大順序串着由64個圓盤構成的塔。目的是將最左邊杆上的盤全部移到中間的杆上,條件是一次只能移動一個盤,且不允許大盤放在小盤的上面。
這是一個著名的問題,幾乎所有的教材上都有這個問題。由於條件是一次只能移動一個盤,且不允許大盤放在小盤上面,所以64個盤的移動次數是:18,446,744,073,709,551,615
這是一個天文數字,若每一微秒可能計算(並不輸出)一次移動,那麼也需要幾乎一百萬年。我們僅能找出問題的解決方法並解決較小N值時的漢諾塔,但很難用計算機解決64層的漢諾塔。
假定圓盤從小到大編號爲1, 2, …
【輸入】
輸入爲一個整數(小於20)後面跟三個單字符字符串。
整數爲盤子的數目,後三個字符表示三個杆子的編號。
【輸出】
輸出每一步移動盤子的記錄。一次移動一行。
每次移動的記錄爲例如 a->3->b 的形式,即把編號爲3的盤子從a杆移至b杆。
【輸入樣例】
2 a b c
【輸出樣例】
a->1->c
a->2->b
c->1->b
AC代碼:
#include<bits/stdc++.h>
using namespace std;
void hanoi(int n, char a, char b, char c){
if(n==1){
cout <<a<<"->"<<n<<"->"<<b;
return;
}else if(n==2){
cout <<a<<"->"<<n-1<<"->"<<c<<endl;
cout <<a<<"->"<<n<<"->"<<b<<endl;
cout <<c<<"->"<<n-1<<"->"<<b<<endl;
return;
}else{
hanoi(n-1,a,c,b); //將 n-1 個 a 藉助 b 從柱子 a 移到柱子 c 上
cout <<a<<"->"<<n<<"->"<<b<<endl;
hanoi(n-1,c,b,a); //將 n-1 個 c 藉助 a 從柱子 c 移到柱子 b 上
}
}
int main(){
int n;
char a='a',b='b',c='c';
cin>>n;
cin >>a>>b>>c;
hanoi(n,a,b,c); //最初目的是將 n 個 a 藉助 c 移到 b
return 0;
}
題解:
困擾了我將近一年的抽象遞歸,現在終於明白一點點了(其實還是沒懂 )
感謝大佬
正解:
將所有盤子從柱子A移動到柱子B上
(1)當N=1 時,只有一個盤子,只需要移動一次:A—>1—>B;
(2)當N=2時,則需要移動三次:
A—>1—> C
A —>2—>B
C —>1—>B
(3)如果N=3,則具體移動步驟爲:
A—>1—> B, A —>2—>C, B —>1—>C. (3.1)
A—>3—>B. (3.2)
C—>1—>A, C —>2—>B, A —>1—>B. (3.3)
會發現當n>=2時是有規律的,可以抽象出將n-1個盤當做一個整體,首先要(藉助b)將n-1個盤從柱子a移動到柱子c,然後將第n個盤子從a移動到柱子b,最後將n-1個盤子(藉助a)從柱子c移動到柱子b上就大功告成了。
例如當n == 2時,將第一個盤子移動到c,然後將第2(n == 2)個盤子從柱子a移動到柱子b,最後將第1個盤子從柱子c移動到柱子b。n==2就可以抽象爲將2個盤子藉助c從a移動到柱子b上。
當n == 3時,可以將3.1看做將1、2盤子藉助b從a移動到柱子c,然後將第3(n == 3)個盤子從a移動到柱子b,最後將1、2盤子藉助a從柱子c移動到柱子b。
同樣n == 4時,可以將前三個盤子藉助b從a移動到柱子c,然後將第4個盤子從a移動到柱子b,最後將前三個盤子藉助a從柱子c移動到柱子b。。。。
我的看法:
hanoi(n,a,b,c)
就是將 n 個 a 藉助 c 移到 b,先不用管 c 有什麼用,已知前三個參數的含義,那麼最後一個參數的含義就是:在 n == 2 時打印出那三條表達式(在 n == 1 時用不到 c)