藍橋杯 漢諾塔 C++算法提高 HERODING的藍橋杯之路

資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
  漢諾塔是一個古老的數學問題:
  有三根杆子A,B,C。A杆上有N個(N>1)穿孔圓盤,盤的尺寸由下到上依次變小。要求按下列規則將所有圓盤移至C杆:
  每次只能移動一個圓盤;
  大盤不能疊在小盤上面。
  提示:可將圓盤臨時置於B杆,也可將從A杆移出的圓盤重新移回A杆,但都必須遵循上述兩條規則。

問:如何移?最少要移動多少次?
輸入格式
  一行,包含2個正整數,一個是N(N<=15),表示要移動的盤子數;一個是M,表示在最少移動d第M步
輸出格式
  共2行。
  第一行輸出格式爲:#No: a->b,表示第M步驟具體移動方法,其中No表示第M步移動的盤子的編號(N個盤子從上到下依次編號爲1到n),表示第M步是將No號盤子從a杆移動到b杆(a和b的取值均爲{A、B、C})。
  第2行輸出一個整數,表示最少移動步數。
樣例輸入
3 2
樣例輸出
#2: A->B
7
數據規模和約定
  0<N<20,0<M<=最小移動步數

解題思路:
對於遞歸的理解,自以爲理解的很透徹了,但是遇到的時候又犯混了,百思不得其解,於是查閱別的博客,終於明白了自己的問題,以前自以爲理解透徹是因爲遞歸不夠複雜,比如樹的中序遍歷,很簡單就是左下、上、右下的遞歸,因爲很容易理解所以往往忽略了最關鍵的地方,就是把大化小。比如這個中序遍歷,我只是想象成一個只有一個根節點,兩個子節點的數,其他的情況都不管了,肯定符合這個最小的樹遍歷的規律。漢諾塔也是同樣的道理,你把漢諾塔中的碟子想象成兩個碟子,那麼思路肯定是把最上面的碟子放到B,把下面的放到C,再把B上的放到C,三個的情況同樣如此,把最上面的兩個碟子放到B,把最下面的放到C,再把B上的兩個碟子放到C,擴展到N個碟子的情況同樣適用。所以,遞歸的關鍵就是隻用考慮最基本的情況,如果最基本的情況都滿足了,那麼所有的情況也都滿足了,只不過多一個遞歸的步驟而已,所以千萬不要想多,把自己繞進去了。當然這道題目還要單獨考慮只有一個碟子的情況。
這道題還有一個複雜的地方在於找出指定步驟移動的盤子,觀察發現,當移動步驟爲指定步驟時,所在遞歸的n的數值就是指定步驟移動的盤子。
代碼如下:

#include<bits/stdc++.h>

using namespace std; 

int sum = 0;

void hanoi(int n, int m, char one, char two, char three)
{
	if(n <= 1){
		sum ++;
		if(sum == m){
		cout << "#" << n << ": " << one << "->" << three << endl;
		}
		return ;		
	}		
	hanoi(n-1, m, one, three, two);//n-1個碟子放到 B上 
	sum ++;
	if(sum == m){
		cout << "#" << n << ": " << one << "->" << three << endl;
	}	
		hanoi(n-1, m, two, one, three);//n-1個碟子放到 C上 
 } 
int main()
{
	int m, n;
	cin >> n >> m;
	hanoi(n, m, 'A', 'B', 'C');
	cout << sum; 
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章