经典问题之汉诺塔

汉诺塔问题:传说从前有一些僧人,他们为一个涉及到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);  
}  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值