《具体数学》(一) 递归问题

普通汉诺塔问题

问题描述请看这里

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;
}

 

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