2018.4.7(程序設計與算法)漢諾塔詳解

問題來源:有三根杆子A,B,C。A杆上有N個(N>1)穿孔圓盤,起初,所有盤子在A柱上,盤的尺寸由下到上依次變小。要求按下列規則將所有圓盤移至C杆:每次只能移動一個圓盤;大盤不能疊在小盤上面。

約束條件:①在小圓盤上不能放大圓盤。②在三根柱子之間一回只能移動一個圓盤。③只能移動在最頂端的圓盤。

問題簡化:3個盤子和3根柱子:A(源)、B(備用)、C(目的)。

解決三個圓盤問題的步驟:a->c ;a->b ;c->b ; a->c ; b->a ; b->c ; a->c

第一步:將A上n-1個盤子藉助C移動到B

第二步:將A最後一個盤子移動到C

第三步:將B上所有盤子(n-1)個藉助A移動到C  

解決問題完成

C語言源代碼:

#include<stdio.h>
void move(char a,char b)
{
printf("%c->%c\n",a,b);
}
void f(int n,char a,char b,char c)  //將n個盤子藉助b塔從a移動到c
{
if(n==1) move(a,c);    //如果只需要移動一個盤子則直接將這個盤子從a移動到c
else                             //否則
{
f(n-1,a,c,b);        //將n-1個盤子藉助c從a移動到b

move(a,c);         //將第n個盤子從a移動到c

                f(n-1,b,a,c);       //將n-1個盤子藉助a從b移動到c

}
}
int main()
{
int n;
scanf("%d",&n);
f(n,'a','b','c'); 

}

以三個盤子爲例,展開說明

①f(3,a,c,b);   //將3個盤子藉助b塔從a移動到c

{  if(n==1)  

  move(a,c);

else

{  f(2,a, c, b);   ② ——> //從此處再展開

move(a,c);

f(2,b,a,c);

}

}


②f(2,a,c,b);   //將3個盤子藉助b塔從a移動到c

{  if(n==1)  

  move(a,c);    //此處實質爲move(a,b)注意上面形參的改變

else

{  f(1,a, c, b);   ③——> //從此處再展開

move(a,c);    //此處實質爲move(a,b)注意上面形參的改變

f(1,b,a,c);

}

}


③f(1,a,c,b);   
{  if(n==1)  
  move(a,c);
else
{  f(1,a, c, b);   
move(a,c);
f(1,b,a,c);
}
}

總結:對於遞歸理解的要點在於放棄! 放棄自己對於理解和跟蹤遞歸全程的企圖,只要理解遞歸兩層之間的交接,以及遞歸終結的條件。




文章來源:網絡        (侵刪)

想象你來到某個熱帶叢林,意外發現了十層之高的漢諾塔。正當你苦苦思索如何搬動它時,林中出來一個土著,毛遂自薦要幫你搬塔。他名叫二傻,戴着一個草帽,草帽上有一個2字,號稱會把一到二號盤搬到任意柱。

你靈機一動,問道:“你該不會有個兄弟叫三傻吧?”
“對對,老爺你咋知道的?他會搬一到三號盤。“
”那你去把他叫來,我不需要你了。“
於是三傻來了,他也帶着個草帽,上面有個3字。

你說:”三傻,你幫我把頭三個盤子移到c柱吧。“
三傻沉吟了一會,走進樹林,你聽見他大叫:”二傻,出來幫我把頭兩個盤子搬到C!“

由於天氣炎熱你開始打瞌睡。朦朧中你沒看見二傻是怎麼工作的,二傻幹完以後,走入林中大叫一聲:“老三,我幹完了!”

三傻出來,把三號盤從A搬到B,然後又去叫二傻:“老二,幫我把頭兩個盤子搬回A!”

餘下的我就不多說了,總之三傻其實只搬三號盤,其他叫二傻出來幹。最後一步是三傻把三號盤搬到C,然後呼叫二傻來把頭兩個盤子搬回C

事情完了之後你把三傻叫來,對他說:“其實你不知道怎麼具體一步一步把三個盤子搬到C,是吧?”

三傻不解地說:“我不是把任務幹完了?”

你說:“可你其實叫你兄弟二傻幹了大部分工作呀?”

三傻說:“我外包給他和你屁相干?”

你問到:“二傻是不是也外包給了誰?“

三傻笑了:“這跟我有屁相干?”

你苦苦思索了一夜,第二天,你走入林中大叫:“十傻,你在哪?”

一個頭上帶着10號草帽的人,十傻,應聲而出:“老爺,你有什麼事?”

“我要你幫把1到10號盤子搬到C柱“

“好的,老爺。“十傻轉身就向林內走。

“慢着,你該不是回去叫你兄弟九傻吧“

“老爺你怎麼知道的?“

“所以你使喚他把頭九個盤子搬過來搬過去,你只要搬幾次十號盤就好了,對嗎?“

“對呀!“

“你知不知道他是怎麼幹的?“

“這和我有屁相干?“

你嘆了一口氣,決定放棄。十傻開始幹活。樹林裏充滿了此起彼伏的叫聲:“九傻,來一下!“ “老八,到你了!““五傻!。。。“”三傻!。。。“”大傻!“

你注意到大傻從不叫人,但是大傻的工作也最簡單,他只是把一號盤搬來搬去。

若干年後,工作結束了。十傻來到你面前。你問十傻:“是誰教給你們這麼幹活的?“

十傻說:“我爸爸。他給我留了這張紙條。”

他從口袋裏掏出一張小紙條,上面寫着:“照你帽子的號碼搬盤子到目標柱。如果有盤子壓住你,叫你上面一位哥哥把他搬走。如果有盤子佔住你要去的柱子,叫你哥哥把它搬到不礙事的地方。等你的盤子搬到了目標,叫你哥哥把該壓在你上面的盤子搬回到你上頭。“

你不解地問:“那大傻沒有哥哥怎麼辦?“

十傻笑了:“他只管一號盤,所以永遠不會碰到那兩個‘如果’,也沒有盤子該壓在一號上啊。”

但這時他忽然變了顏色,好像泄漏了巨大的機密。他驚慌地看了你一眼,飛快地逃入樹林。

第二天,你到樹林裏去搜尋這十兄弟。他們已經不知去向。你找到了一個小屋,只容一個人居住,但是屋裏有十頂草帽,寫着一到十號的號碼。



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