您的位置:首页 > 其它

经典问题之汉诺塔

2015-08-25 16:03 465 查看
汉诺塔问题:传说从前有一些僧人,他们为一个涉及到64个石盘的难题困惑不已。僧人的目的是将全部石盘从一个塔移动到另一个塔,中间能够借助第三个塔,一旦完成,时间就会停止(也就是世界末日就会来临)。注意:这64个盘子的直径从上到下逐渐增加,需要每次将一个盘子从一个塔子移动到另一个塔,任何盘子都能从任何塔移动到其他任何一个塔,唯一的规则是不能将较大的盘子放在较小的盘子上。现在,我们不考虑其富有的神话意义,我们感兴趣的是怎么用现在的技术来解决这个问题。

汉诺塔问题是典型的递归问题,递归思想的核心是:

- 没有无穷递归;

- 每个停止情况都执行那种情况下的正确的操作;

- 针对牵涉递归的每一种情况,如果所有递归调用都正确执行他们的操作,那么整个情况都会正确执行。

下面我们来分析其具体实现:

- 当只有一个盘子时,可以将这个盘子直接从塔(A)移动到第三个塔(C);(即递归终止情况,不会存在无穷递归)

- 当A塔有两个盘子时,需要将第一个塔上的第一个盘子移动到第二个(B)上,然后将第一个塔上的第二个盘子移动到C塔上,最后将B塔上的盘子移动到C塔上;

- 当A塔有三个盘子时,需要将A塔上的上面两个盘子移动到B塔(需要借助目标塔),然后将A塔上最大的盘子移动到C塔,最后将B塔上的两个盘子借助A塔移动到C塔上。

- 当A塔有n个盘子是,先将A塔上编号1至n-1的盘子(共n-1个)移动到B塔上(借助C塔),然后将A塔上最大的n号盘子移动到C塔上,最后将B塔上的n-1个盘子借助A塔移动到C塔上。(运用了数学归纳法,即每种执行情况结果准确)

下面是具体的代码实现:

#include<iostream>
#include<cstdlib>
using namespace std;

//记录步数
int i=1;
void move(int n,char source,char target) //将编号为n的盘子由source塔移动到target塔
{
cout << "第" <<i<<"步:" << "将" <<n<< "号盘子从"<<source <<"移动到"<<target << endl;
i++;
}

//source为初始塔,middle为借助塔,target为目标塔
//将n个盘子由初始塔移动到目标塔
void hanoi(int n,char source,char middle,char target)
{
if (n==1)
move(1,source,target);//只有一个盘子是直接将初始塔移动到目标塔
else
{
//先将初始塔的前n-1个盘子借助目标塔移动到中间塔上
hanoi(n-1,source,target,middle);

//将剩下的一个盘子移动到目标塔上
move(n,source,target);

//最后将中间塔上的n-1个盘子移动到目标塔上
hanoi(n-1,middle,source,target);
}
}

void main()
{
cout << "请输入盘子的个数:\n";
int n;
cin >> n;
const char x='A',y='B',z='C';
cout << "盘子移动情况如下:\n";
hanoi(n,x,y,z);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法