汉诺塔问题是大家理解递归的一个基础问题。看了很多博客都不是很理解,下面我将从最简单的解法为大家讲解:
1.首先是一个盘子,即A塔上有1个盘子的情况(Emmm,画图水平有限,仅限说明问题);
这是我们只需要将A中的盘子移到C中,经过一次操作即可:The 1:{A}-->{C}
2.两个盘子的情况:
只需要进行如上三步就可以:
The 1:{A}-->{B} The 2:{A}-->{C} The 3:{B}-->{C}
从这三步我们可以看出,我们这里将B作为一个缓冲柱来看待。先将小盘移到B,再将大盘移到C,然后再把小盘移到C。
3.两个盘子可能还是发现不了规律,我们再推广成三个盘子看一下:
通过以上七步,我们可以验证A中有两个盘子的结论,我们不断地将A柱和B柱当成缓冲柱。将所有盘子移动到C柱上。
在这里,我们思考一下:
解决三个盘子的问题可不可以看成解决两个盘子的问题呢?
我们把三个盘子的上边两个小盘子看成一个盘子。
然后我们要如何处理呢?
这样是不是就变成了两个盘子的移动。
当N变成64,也就是初始A柱上有64个盘子时,我们把前63个盘子看成一个整体移动到B,然后把第64个最大的盘子移动到C,最后再把B柱上的63个盘子看成一个整体移动到C盘上。这就相当于把64个盘子的规模转化成了63个盘子。
那么63个盘子要如何移动呢?
我们把前62个盘子看成一个整体,把前62个盘子从A柱移动到B柱,然后再把第63个大盘子从A柱移动到C柱,最后将B柱上的62个盘子堪称一个 整体移动到C柱上,就完成了63个盘子的移动。
以此类推:
我们会发现问题规模会不断的缩小。直到1个盘子的情况。
例如。N初始值为3,即A上有三个盘子:
通过我们的递推求解,要想解决三个盘子的情况,先解决 n-1即2个盘子的情况。
要想解决两个盘子的情况要先解决n-1即1个盘子的情况。
我们把一个盘子从A移动到C后,递归回溯,再把第二个盘子从A移动到B,最后把C上的盘子移动到B上,这样两个盘子的情况解决完,接着解决三个盘子的情况,把最后最大的盘子移动到C,然后把B中的最小盘子移动到A,然后把B中的第二个盘子移动到C,最后把A中的最小盘子移动到C,就成功解决了问题。
最后贴一下代码:
#include<iostream>
using namespace std;
int i=0;
//n:A中初始的盘子数量
//a:A柱的名称
//b:B柱的名称
//c:C柱的名称
int hannuota(int n,char a,char b,char c)
{
if(n==1)
{
i++;
printf("The %d:{%c}-->{%c}\n",i,a,c);//如果只有一个盘子就直接从A移动到C
}
else
{
hannuota(n-1,a,c,b);//把n-1个盘子看成一个整体从A移动到B
hannuota(1,a,b,c); //最大的一个盘子移动到C
hannuota(n-1,b,a,c);//最后把B中的n-1个盘子看成一个整体移动到B
}
}
int main()
{
hannuota(3,'a','b','c');
return 0;
}
代码完全按照以上分析的思想进行撰写。
有同学可能对递归不太了解,这里以N=3对递归进行分析,如图:
感觉大家观看,有什么写的不好的不对的地方请留言给出。谢谢。嘿嘿。