《具體數學》(一) 遞歸問題

普通漢諾塔問題

問題描述請看這裏

a,b,c三個圓柱,把a上面的圓盤按照小的盤子只能放在大的上面的規則通過b移動到c上(從上到下爲從大到小!)。

這個問題想必在課堂上(老師會說不用考慮中間過程是怎麼進行的),書上或者某處看到過,

在這裏我們把64片黃金圓盤改成爲n(畢竟這是個數學問題),然後設把i個盤子從a通過b移動到c上(盤)所需要的移動次數爲T(i)

(1<=i&&n>=i),我來解釋一下爲什麼要重點標記這個"設",因爲在這裏把i個盤子從a移動到c和a移動到b的原理是一樣的(後面會用到這個解釋)。

       要把n個盤子移動c上,需要先將a上面的n-1個盤子移動到b上,再將第n個盤子移動到(按照上面的解釋這裏用了T(n-1)),then把第n個盤子放到c上(移動了1次),記住這裏還沒完,因爲,我們還沒把n-1盤子移動到c上(所以這裏還有T(n-1)次,原因看解釋),所以T(n)=2*T(n-1)+1 次,然後依次地推到T(1)=1,就可以通過求解下列遞推式得出次數。

                                                          T(n)=\left\{\begin{matrix} 2*T(n-1)+1,&n>1 \\ 1,n=1& \end{matrix}\right.;

#include<iostream>

using namespace std;

typedef long long ll;

int count=0;

void move(ll n,char a,char c)
{
	count++;
	cout << count << ':' << a << "->" << c <<endl;
}

void h(ll n,char a,char b,char c)
{	
	if(n==1)
	{
		move(n,a,c);
	}
	else
	{
		h(n-1,a,c,b);
		move(n,a,c);
		h(n-1,b,a,c);
	}
	
}

int main()
{
	ll n=3;
	
//	cin>>n;
	
	h(n,'a','b','c');
	
	return 0;
}

擴展一下:

在原來的基礎下,加上一個條件:a上的盤子,不能直接移動到c上

解法類似,先設T(i)爲把i個盤子從a經過b移動到c(不直接從a移動到c)上所需要的次數,同理把i個盤子從c經過b移動到a上需要的次數爲T(i)次

步驟:

1)先把n-1個盤子從a移動到c上,次數爲T(n-1)

2)再把第n個盤子移動到b上,次數爲1

3)在把n-1個盤子從c移動到a上,次數爲T(n-1)

4)再把第n個盤子從b移動到c上,次數爲1

5)最後把n-1個盤子從a移動c上,次數爲T(n-1)

綜上所述:T(n)=3*T(n-1)+2

so:

#include<iostream>

using namespace std;

long long cou;

void mov(char a,char b)
{
    cou++;
    cout<<cou<<a<<b<<endl;
}

void h(int n,char a,char b,char c)
{
    if(n==1)
    {
        mov(a,b);
        mov(b,c);
    }
    else
    {
        h(n-1,a,b,c);
        mov(a,b);
        h(n-1,c,b,a);
        mov(b,c);
        h(n-1,a,b,c);
    }
}

int main()
{
    int n;
    
    cin>>n;

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

    return 0;
}

 

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