怎麼理解漢羅塔問題 漢諾塔問題(三柱及四柱)詳解

2021-10-16 13:25:38 字數 2813 閱讀 1338

漢諾塔(hanoi tower),又稱河內塔,傳說大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片**圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,任何時候,在小圓盤上都不能放大圓盤,且在三根柱子之間一次只能移動乙個圓盤。問應該如何操作?

需要求兩個問題,一是求所需要的步數,二是求移動過程中每一步的做法步驟

漢諾塔問題-步數

關於步數  是個很簡單的問題  高中大家都學過  可能也做過類似的題

如果a上有n個盤子  要借助b柱子將他們移動到c上  那麼  我們設總共需要移動步數為f(n)

那麼 我們先將 最上面的n-1個盤子   借助c柱子移動到b上  毫無疑問需要步數  f(n-1)

那麼 我們再把a上剩下的乙個盤子  移動到c上 需要一步  然後再把b上的n-1個借助a移動到c上  需要f(n-1)

到這就完成了所有的移動  總共步數f(n)=2*f(n-1)+1

n=1的時候需要一步  所以 n就需要 2的n次方再減1   (

)#include

#include

int main(){

int n;

scanf("%d",&n);

printf("%d",(int)pow(2,n)-1);

return 0;

這裡要注意範圍  如果n比較大的話可以用long long,時間上可以用快速冪優化

漢諾塔問題-步驟

關於 步驟,同樣的遞迴思想

我們假設 函式  hanoi ( a , b , c , n )代表  把a上的n個盤子借助b移動到c的步驟

那麼  如果n==1  則步驟就是  a->c  一步就好了

n不等於1 的時候  我們先把a上n-1個盤子借助c移動到b上  就是 hanoi ( a , c , b , n-1 )

再把a上最後乙個挪到c     a->c

最後再把 b上n-1個盤子借助a挪到c上  hanoi ( b , a , c , n-1 )

整個過程就完成了   主要是要理解遞迴的思想  理解了思想  遞迴的程式寫起來是最簡單的

**#include

void hanoi(char a,char b,char c,int n){

if(n==1){

printf("%c->%c ",a,c);

else{

hanoi(a,c,b,n-1);

printf("%c->%c ",a,c);

hanoi(b,a,c,n-1);

return ;

int main(){

int n;

scanf("%d",&n);

hanoi('a','b','c',n);

return 0;

漢諾塔問題拓展之四柱漢諾塔

在原來的問題上再加乙個柱子  其他的條件不變

將a柱上的n個圓盤 移到d柱上  同樣大的不能壓到小的

我們同樣用三柱的方法分析問題

1、我們設將a柱最上邊的x個圓盤(1<=x

2、然後我們再把a柱上剩下的n-x個盤借助b柱移動到d柱上(不能借助c  c上的都小),那麼這一步驟和三柱漢諾塔是一樣的,我們剛才算過了,是

3、最後我們再把c上的x個圓盤借助a、b移動到d上    同樣需要f[ x ]步

那麼 總步數 f[n]=2*f[ x ] +這就是我們最終得到的式子

(這裡 注意一下這個x的取值範圍啊   是  (1<=x

如果x為0的話,那麼相當於我們第一步和第三步沒做任何事,只做了第二步,那麼豈不是和三柱的情況一樣了 ,有乙個柱子都沒用,肯定不是最優解。

如果x為n的話 那我們第二步沒做任何事 第一步和第三步 先借助b、d挪到了c 再借助 a、b挪到了d  那幹嘛不一步直接挪到d,所以也肯定不是最優解)

這個式子關鍵是f[ x ]的取值   f[ 1 ] = 1    f[ 2 ] = 3  這兩個我們不用說 很清楚

那麼從n=3 開始   我們求解時利用前邊已知的f[ x ]  挨個列舉  留下最小值 就是答案了

**在放**之前還有個小問題  這裡由於需要計算乙個的值  我們在列舉的時候可能會列舉到x等於1 n等於64的情況

那麼   2的63次方  我們知道  longlong也存不下  可能有的同學會考慮高精度大數了  其實不用  我們要知道  我們在列舉過程中 是想找到那個最小的數  那麼 過大的數字 我們雖然存不下  其實他對我們也沒啥用處

而且 事實證明  64以內的所需步數是很小的  64的時候只需要18433步

那麼我們只要設定乙個最大值 比如是十萬  然後 列舉過程中 比這個值小的 我們才更新

這樣一來  int就可以解決64以內的了

#include

#include

#include

#include

#include

using namespace std;

typedef long long ll;

int f[100];

int inf=100000;//設定最大值

void sv(int n){

f[1]=1;

f[2]=3;

for(int i=3;i<=n;i++){

f[i]=inf;//f[i]先置為最大值 方便後邊比較

for(int x=1;x

if( (2*f[x]+pow(2,i-x)-1)

f[i]=2*f[x]+(int)pow(2,i-x)-1;

int n;

int main(){

sv(65);

while(~scanf("%d",&n)){

printf("%d\n",f[n]);

怎麼理解漢羅塔問題 教你輕鬆理解漢諾塔問題

漢諾塔的解決在程式裡實際上是乙個函式遞迴呼叫的過程。假設a上有 n個盤子,求解的大 致想法是想把 a最上面的 n 1個盤子借助c挪到 b,接著把 a最下面的最大的盤子挪到 c,再把b上的 n 1個盤子借助a挪到 c,完成。首先先看 c 裡解決這個問題的 using system using syst...

漢羅塔問題

1.漢諾塔問題描述 有3根柱子a,b,c,a柱上有n個盤子,盤子的大小不等,大的盤子在下,小的盤子在上。要求將a柱上的n個盤子移到c柱上,每次只能移動乙個盤子。在移動過程中,可以借助於任何一根柱子 a b c 但必須保證3根柱子上的盤子都是大的盤子在下,小的盤子在上。2.源程式 注 源程式中的x,y...

漢羅塔問題

漢羅塔的移動序列為2 n 1 次 漢羅塔問題的遞迴解 演算法目的 把是start柱子上的木塊移動到end柱子上 當start柱子上只有兩個圓環時,把兩個圓環放到end柱子上要借助middle柱子,這樣start柱子上有n個圓環時,要先把第n個圓環上的n 1各圓環移動到middle柱子上,然後再把第n...