1. 程式人生 > >hdu1997 漢諾塔VII(DFS遞迴呼叫)

hdu1997 漢諾塔VII(DFS遞迴呼叫)

題目詳情:傳送門

       我都要做鬱悶了,邏輯一直沒錯,但是最後一組答案就是過不了。看了幾個小時,終於發現問題所在了。我把陣列初始化 memset() 函式,放在了自定義函式 Input 中,使用形參的sizeof()作為地址的長度,結果陣列沒有初始化成功,導致悲劇的誕生。之後我把 memset() 中的地址長度改回陣列長度問題終於解決了可憐。剛做這一題時我把它當成棧混洗了委屈,結果一直沒琢磨明白。之後在網上一查,恍然大悟。霎時間,感覺好難過,為什麼自己就沒想到。下面我們來分析一下本題的思路吧。

分析:

        這一題考查的遞迴的使用,又是一個以漢諾塔為載體的題目。用到遞迴那就要回歸到這個問題的本質:既然要最優解,那麼怎麼樣的才是最優解?如果你能想到這裡,那麼你就很接近成功了。其實要得到最優解的步驟其實只有三個:①先將第n個圓盤上的 n-1 個圓盤從 柱A 移動到 柱B ②將第n個圓盤從 柱A 移動到 柱C ③然後將之前的n-1個圓盤,再移到 柱C。通過這三個步驟,就可以以最優解的方式完成從 柱A 到 柱C 的移動。由此可見,要把n個圓盤從 柱A(藉助柱B)移動到 柱C,那麼一定要把第n個圓盤移動到 柱C,換而言之,就是 第n個圓盤一定是在 柱A 和 柱C 之間的,如果不在那麼肯定不是最優解。以此類推,要將n-1個圓盤從柱A(藉助柱C)移動到 柱B,那麼第 n - 1個圓盤 一定在 柱A 和 柱B 之間。到了這裡問題就基本解決了,剩下的就只有用你的雙手在鍵盤上飛舞就可以了。

本題程式碼如下:

#include <stdio.h>
#include <string.h>
#define MAXN 65 + 10
void Input(int *in_arr){
	int i;
	memset(in_arr,0,MAXN*sizeof(int) );
	scanf("%d",&in_arr[0]);
	for(i = 1; i <= in_arr[0]; i++)
		scanf("%d",&in_arr[i]);
}
bool hanoi(int n,int *a,int *b,int *c){
	if(!n)					//如果n等於0,那麼當然就是true
		return true;
	if( n == a[1] )			//如果第n個圓盤在柱A上,那麼就將 柱A 上的n-1個圓盤(除第n個圓盤以外的圓盤)通過 柱C 移動到 柱B 上
		return hanoi(n-1,++a,c,b);
	else if(n == c[1])		//如果第n個圓盤在柱C上,那麼就將 柱B上的n-1個圓盤,通過柱A移動到柱B上
		return hanoi(n-1,b,a,++c);
	return false;			//否則返回false
}
int main(){
	int T,n;
	int A[MAXN],B[MAXN],C[MAXN];
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		Input(A);
		Input(B);
		Input(C);
		if(hanoi(n,A,B,C))
			printf("true\n");
		else
			printf("false\n");
	}
	return 0;
}

(如有錯誤,歡迎指正,如有轉載請註明出處)