汉诺塔问题

本文详细介绍了经典的汉诺塔问题,从最基本的问题出发,探讨了递归解决方案,并逐步展开讨论了简单变形、四柱汉诺塔问题、更改移动方式问题以及询问每个盘子移动次数的特殊情况。通过分析,给出了不同情况下的移动策略和公式,揭示了汉诺塔问题的递归本质。
摘要由CSDN通过智能技术生成

汉诺塔问题(Hanoi)


汉诺塔问题,一直是递归问题的典范。同时这个问题也随着时间的发展而推陈出新,一步步考验着人类的智商。在这里做一些总结,但因笔者才疏学浅。如有不足希望指正。

最基本的问题

题目描述:

汉诺塔由编号为1到n大小不同的圆盘和三根柱子a,b,c组成。开始时,这n个圆盘由大到小依次套在a柱上,如图所示。要求把a柱上n个圆盘按下述规则移到c柱上:

  1. 一次只能移一个圆盘,它必须位于某个柱子的顶部;
  2. 圆盘只能在三个柱上存放;
  3. 任何时刻不允许大盘压小盘。

将这n个盘子从a柱移动到c柱上,最少需要移动多少次?

Solution:

直接递归就可以了,假设最初在a号柱子上有N个盘子,并且由上到下半径依次增大,那么我们可以把上面的n-1个盘子看成一个整体,而我们现在要做的就是把n-1个盘子从a移动到b,然后把最大的盘子由a移动到c再把那n-1个盘子由b移动到c。

其实随着思考的深入,你会发现,其实在 汉诺塔 问题中,我们其实想要实现的就是把n个盘子从一根柱子移动到另一个柱子上,而我们只不过不得不借助另一个柱子来帮助实现而已。

所以,现在我们的原问题就可以转化为一个较简单的子问题,也就是把剩下的n-1个盘子,由一根柱子,转移到另根柱子就可以了。

现在我们可以无限的递归下去,直到只剩下一个盘子,那么答案显然就是1了。这样我们再一点点的回溯回去,就可以得到答案了。

Code:

#include<stdio.h>
void hanoi(int n,char a,char b,char c)
{
    if(n==1)
    {
        printf("%d:%c->%c\n",1,a,c);
    }
    else
    {
        hanoi(n-1,a,c,b);//用 b 柱作为协助过度,将 a 上的(n-1)片移到 c 上 
        printf("%d:%c->%c\n",n,a,c);
        hanoi(n-1,b,a,c);//用 c 柱作为协助过度,将 b 上的(n-1)片移到 a 上 
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    hanoi(n,'A','B','C');
    return 0;
}

简单的变形

  • 原问题中,我们是n个盘子,移动到三根柱子上,上面的代码是用了递归的思想进行了路径的输出。

当我们想要知道方案数的时候,不妨可以打表看一下:

n 方案数
3 7
4 15
5 31
6 63

这个时候好像就可以知道好像可以递推出n个盘子的公式:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值