牛客网考研机试题汉诺塔III【递归】

汉诺塔III

题目

19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。
目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。
现在我们改变游戏的玩法,不允许直接从最左()边移到最右()(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。
Daisy已经做过原来的汉诺塔问题和汉诺塔II,但碰到这个问题时,她想了很久都不能解决,现在请你帮助她。现在有N个圆盘,她至少多少次移动才能把这些圆盘从最左边移到最右边?

输入:包含多组数据,每次输入一个N值(1<=N<=35)
输出:对于每组数据,事业处移动最小的次数
样例输入:
1
3
12
样例输出:
2
26
531440

思路:经典的汉诺塔问题中没有“只能从中间杆移出或移入中间 ”这一条件的限制,用递归的想法是:如果有N个圆盘要从a移动c,第一步,先把上面N-1个圆盘从a移到b;第二步,把第N个移到c;第三步:把N-1个圆盘从b移至c。如果用F(N)表示将N个圆盘从一个位置移动到另一个位置的次数,那么可以写出式子:F(N)=2*F(N-1)+1。

相应的可以分析本题,加上“只能从中间杆移出或移入中间 ”这一条件的限制,用递归的想法是:如果有N个圆盘要从a移动c,第一步,先把上面N-1个圆盘从a移到b再移到c;第二步,把第N个移到b;第三步,把上面N-1个圆盘从c移到b再移到a;第四步,把第N个移到c;第五步,把上面N-1个圆盘从a移到b再移到c。为什么对于一三五的步骤我不拆开写呢,写成两个步骤?因为F(N)被定义成:将N个圆盘从a移到c(或者c到a)的次数,所以从a到b,b到c就合成一个步骤写了。可以写出式子:F(N)=3*F(N-1)+2。这样递归的关系出来了,代码就很好写了。

代码

#include
using namespace std;

long long fact(int n)
{
	if(n==1)
	{
		return 2;
	}
	else
	{
		return 3*fact(n-1)+2;
	}
}

int main()
{
	int n;
	long long result;
	while(cin>>n)
	{
		result = fact(n);
		cout<<result<<endl;
	} 
		
}

总结

当初学汉诺塔问题(数据结构)的时候就迷迷糊糊的,现在多看几遍基本上能搞懂了。拿到递归问题,要能把一个复杂的大问题转化为与原问题相似但规模较小的问题来求解。

你可能感兴趣的:(考研机试,算法,数据结构)