您的位置:首页 > 其它

汉诺塔问题及其变型

2016-02-25 22:22 323 查看
一.汉诺塔问题

(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  汉诺塔问题 递归