遞歸---漢諾塔

【題目描述】

約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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章