汉诺塔问题及其变型

一.汉诺塔问题

(1)问题描述:

有三个柱子A、B、C,A柱子上有n个圆盘,圆盘的大小不等,大圆盘的在下,小圆盘的在上。

将A柱子上的圆盘全部移动到C柱子上。每次只能移动一个圆盘,而且在移动的过程中,

三个柱子上的圆盘始终保持大圆盘在下,小圆盘在上。

(2)程序输入:
A柱子上的圆盘数,当输入0时,程序结束。 
(3)程序输出:
圆盘移动的过程和圆盘移动的总次数。
(4)递推公式:
H(1) = 1.

H(n) = 2 * H(n-1) + 1 = 2 ^ n - 1.

//源代码已经在VS2012编译通过。
#include<windows.h>
#include<string>
#include<iostream>
using namespace std;
//将num号圆盘从x柱子移动到y柱子
void Move(int num,string x,string y)
{
    cout << num << "号圆盘:" << x << "移动到" << y << endl; 
}
//将A柱子上的n个圆盘移动到C柱子上,B柱子作为中间柱子,返回移动总次数
long long Hannoi(int n,/*源柱子*/string A,/*中间柱子*/string B,/*目标柱子*/string C)  
{
    long long cnt1,cnt2;
    if (n == 1)  
    {
		//A柱子上只有一个圆盘时,直接将这个圆盘移动到C柱子上,移动次数是1
        Move(1,A,C);
        return 1;
    }
    else
    {
		/******************************************************************            
		1                                                                1
	   	2                       1                 1                      2
		3             =>        2       =>        2       =>             3
		4                       3                 3                      4
		5                  5    4                 4    5                 5
       ***  ***  ***      ***  ***  ***     ***  ***  ***     ***  ***  ***
	    A    B    C        A    B    C       A    B    C       A    B    C
		*******************************************************************/
		//将A柱子上的最上面n-1个圆盘移动到中间柱子B上
        cnt1 = Hannoi(n - 1,A,C,B);
		//将A柱子上的最下面一个圆盘移动到C柱子上
        Move(n,A,C); 
		//将中间柱子B上的n-1个圆盘移动到C柱子上
        cnt2 = Hannoi(n - 1,B,A,C);  
        return cnt1 + cnt2 + 1;  
    }  
}  
int main ()  
{
	cout << "汉诺塔问题的解决方案:" << endl;
    long long cnt;  
	int n;
	cout << "请输入A柱子上的圆盘数:";
	while(scanf("%d",&n) != EOF)
	{
		if(n == 0)
		{
			break;
		}
		cnt = Hannoi (n,"A","B","C");  
		cout << n << "个圆盘的移动总次数:" << cnt << endl; 
		cout << "请输入A柱子上的圆盘数:";
	}
    system("pause");
	return 0;  
} 

二.汉诺塔问题的变型

(1)问题描述:
有三个柱子A、B、C,A柱子上有n个圆盘,圆盘的大小不等,大圆盘的在下,小圆盘的在上。
将A柱子上的圆盘移到C柱子上。每次只能移动一个圆盘,而且在移动的过程中,

三个柱子上的圆盘始终保持大圆盘在下,小圆盘在上。

另外,不允许直接从A柱子移动到C柱子或直接从C柱子移动到A柱子,
即每次移动一定是移动到中间柱子B或者从中间柱子B移走。

例如,当A柱子上只有一个圆盘时,
首先将这个圆盘从A柱子移动到中间柱子B,再从中间柱子B移动到C柱子,总共移动次数是2。

(2)程序输入:
A柱子上的圆盘数,当输入0时,程序结束。 
(3)程序输出:
圆盘移动的过程和圆盘移动的总次数。
(4)递推公式:
H(1)= 2.
H(n) = 3 * H(n-1) + 2.

//源代码已经在VS2012编译通过
#include<windows.h>
#include<string>
#include<iostream>
using namespace std;
//将num号圆盘从x柱子移动到y柱子
void Move(int num,string x,string y)
{
	if(x == "B" || y == "B")
	{
		cout << num << "号圆盘:" << x << "移动到" << y << endl;
	}
	else
	{
		cout << num << "号圆盘:" << x << "移动到" << "B" << endl; 
		cout << num << "号圆盘:" << "B" << "移动到" << y << endl;
	}
}
//将A柱子上的n个圆盘移动到C柱子上,B柱子作为中间柱子,返回移动总次数
long long Hannoi(int n,/*源柱子*/string A,/*中间柱子*/string B,/*目标柱子*/string C)  
{
    long long cnt1,cnt2,cnt3;
    if (n == 1)  
    {
		//A柱子上只有一个圆盘时,首先将这个圆盘移动到中间柱子B上,再从中间柱子B上移动到C柱子上
		//移动次数是2
        Move(1,A,C);
        return 2;
    }
    else
    {
		/***************************************************************************            
		1                                                                        1
	   	2                    1           1     1            1                    2
		3         =>         2 =>        2 =>  2         => 2         =>         3
		4                    3           3     3            3                    4
		5            5       4        5  4     4   5        4       5            5
       *** *** ***  *** *** ***  *** *** ***  *** *** ***  *** *** ***  *** *** ***
	    A   B   C    A   B   C    A   B   C    A   B   C    A   B   C    A   B   C
		***************************************************************************/
		//将A柱子上的最上面n-1个圆盘移动到C柱子上
        cnt1 = Hannoi(n - 1,A,B,C);
		//将A柱子上的最下面1个圆盘移动到B柱子上
        Move(n,A,B); 
		//将C柱子上的n-1个圆盘移动到A柱子上
        cnt2 = Hannoi(n - 1,C,B,A);
		//将B柱子上的1个圆盘移动到C柱子上
		Move(n,B,C); 
		//将A柱子上的n-1个圆盘移动到C柱子上
        cnt3 = Hannoi(n - 1,A,B,C);
        return cnt1 + cnt2 + cnt3 + 2;//cnt1 == cnt2 == cnt3 
    }  
}  
int main ()  
{
	cout << "汉诺塔问题的解决方案:" << endl;
    long long cnt;  
	int n;
	cout << "请输入A柱子上的圆盘数:";
	while(scanf("%d",&n) != EOF)
	{
		if(n == 0)
		{
			break;
		}
		cnt = Hannoi (n,"A","B","C");  
		cout << n << "个圆盘的移动总次数:" << cnt << endl; 
		cout << "请输入A柱子上的圆盘数:";
	}
    system("pause");
	return 0;  
} 







  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值