-
题目描述:汉诺塔问题是一个经典的问题,其来源据说在19世纪末欧洲的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆自上而下、由小到大顺序串着64个圆盘构成的塔,游戏的目的是将左边A杆上的圆盘借助最右边的C杆,全部移动到中间的B杆上,条件是一次仅能移动一个盘,且不允许大盘放在小盘上面,问最少需要移动多少次。
-
解法描述:我们可知限制条件为:一次只能移动一个盘,且不允许大盘放在小盘上面。解法为:首先我们设要解决的汉诺塔有n个圆盘,对A杆上的全部n个圆盘从小到大顺序编号,最小的为1号,依次递增,最大的圆盘编号为n。
-
第一步:假设此时A杆上只有一个圆盘,即汉诺塔只有一层,那么将其移动到B杆上即可。
-
第二步:对于有n(n>1)个圆盘的汉诺塔,将n个圆盘分为两个部分,上面n-1个圆盘为一个部分,下面编号为n的一个圆盘为另一部分。
-
第三步:将“上面n-1个圆盘“看成一个整体,为了解决这n个圆盘的汉诺塔可以进行下列操作:
- 将A杆上的n-1个圆盘借助B杆移到C杆上,此时设C杆上有n个盘子(n = n - 1);
- 将A杆上剩下的编号为n的盘子移动到B杆上;
- 将C杆上的n-1个盘子借助A杆移到B杆上;
- 在将n-1个圆盘从C杆上移动到B杆上和原问题具有具有相同的特征属性,只是问题的规模小于原问题,故我们可以使用递归的方法来求解。
-
-
下面就以四个盘子为例,来解释盘子的移动过程:
- 初始状态的汉罗塔:
- 第一次借助B杆将A杆上的n-1个盘子移动到C杆上并把A杆上的最后一个盘子移动打B杆上后的结果(中途的移动步骤没有体现出来,需要自己下去推导,这里就给出了每次移动后的最终结果):
- 再借助B杆将C杆上的n-1个盘子移动到A杆并将C杆上的最后一个盘子移动到B杆上后的结果:
- 递归对A杆、B杆和C杆上的盘子的移动操作直至最后一个盘子移动到B杆上结束;
- 最后的结果:
编程实现:
- 初始状态的汉罗塔:
#include<iostream>
using namespace std;
void Hanoi(int n, char a, char b, char c, int &count)
{
if(n == 1)
{
count++;//移动A杆上的最后一个盘子到B杆
}
else
{
Hanoi(n - 1, a, b ,c, count); //A 杆借助B杆移动n-1个盘子到C杆
count++; //移动A杆上的最后一个盘子到B杆
Hanoi(n - 1, c, b ,a, count); //C杆借助B杆将n-1个盘子移动到A杆
}
}
int main()
{
int count,n;
cout << "please input the count:";
cin >> n;
count = 0;
Hanoi(n, 'A', 'B', 'C', count);
cout << "total = " << count << endl;
return 0;
}
- 测试结果: