一.汉诺塔问题
(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;
}