汉诺塔

汉诺塔(Towers of Hanoi)问题来自一个古老的传说:在世界刚被创建的时候有一座钻石宝塔(塔1),其上有64个金碟(如图5-4所示)。所有碟子按从大到小的次序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔(塔 2和塔3)。从世界创始之日起,婆罗门的牧师们就一直在试图把塔1上的碟子移动到塔2上去,其间借助于塔 3的帮助。由于碟子非常重,因此,每次只能移动一个碟子。另外,任何时候都不能把一个碟子放在比它小的碟子上面。按照这个传说, 当牧师们完成他们的任务之后,世界末日也就到了。

 

在汉诺塔问题中,已知 n个碟子和3座塔。初始时所有的碟子按从大到小次序从塔1的底部 堆放至顶部,我们需要把碟子都移动到塔2,每次移动一个碟子,而且任何时候都不能把大碟子放到小碟子的上面。在继续往下阅读之前,可以先尝试对 n=2,3和4来解决这个问题。

 

一个非常优雅的解决办法是使用递归。为了把最大的碟子移动到塔2,必须把其余n-1个碟 子移动到塔3,然后把最大的碟子移动到塔2。接下来是把塔3上的n-1个碟子移动到塔 2,为此可以利用塔2和塔1。可以完全忽视塔2上已经有一个碟子的事实,因为这个碟子比塔3上将要移 过来的任一个碟子都大,因此,可以在它上面堆放任何碟子。


可以得到碟子的移动次数moves (n)如下:


得到的结果应为moves (n)=2n-1,函数的复杂性为 (2n )。


代码实现:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <stack>
using namespace std;

stack<int> s[4];
//从init_T移动n个碟子到end_T,使用temp_T作为碟子的中间存储
void Hanoi(int n,int init_T,
	int end_T,int temp_T)
{
	//停止条件:移动一个碟子
	if (n==1)
	{
		s[init_T].pop();
		s[end_T].push(n);
		cout<<"move dish"<<n<<" frome "<<" T"<<init_T<<" to "
			<<" T"<<end_T<<endl;
	}
	else
	{
		//从init_T到temp_T移动n-1个碟子,使用end_T进行临时存储
		Hanoi(n-1,init_T,temp_T,end_T);
		s[init_T].pop();
		s[end_T].push(n);
		//移动最大的碟子到end_T
		cout<<"move dish"<<n<<" frome "<<" T"<<init_T<<" to "
			<<" T"<<end_T<<endl;
		//从temp_T到end_T移动n-1个碟子,使用init_T进行临时存储
		Hanoi(n-1,temp_T,end_T,init_T);
	}
}
//初始化
void InitHanoi(int n)
{
	for (int d=n; d>0; d--)
	{
		s[1].push(d);//把碟子d 放到塔1上
	}
	Hanoi(n,1,2,3);
	for (int i=1;i<=n;i++)
	{
		cout<<s[2].top()<<endl;
		s[2].pop();
	}
}
int main()
{
	int n;
	cout<<"Enter the number of dish: ";
	cin>>n;
	cout<<"The solution for n= "<<n<<endl;
	InitHanoi(n);
	return 0;
}


测试结果

     

    






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值