#汉诺塔
汉诺塔问题源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。有如下题目:一根柱子上有n个圆盘,现要求遵循以上规则将其移动到一根空柱子上,求最小移动次数。
思路分析:对待许多以现实生活为基础的编程问题,我们可以将它分成两步:
1、过程模拟 2、程序模拟
具体地来说一下,就是先将问题本身利用各种各样的方法进行模拟成一个数学过程,随后将该数学过程用程序的形式表达出来。
说起来容易,做起来却着实需要花费不少功夫。那么我们该如何将摆盘子这种事模拟成数学过程呢?
分析过程:我曾尝试正向分析,逆向分析,却都无法得出结果,因为任务量太过庞大,人类的working memory着实有限,所以我不得不放弃与之正面“硬刚”,尝试采用较为巧妙的方法–递归。在我的理解中,递归可以想象成一次正向上抛运动,其特点是“有来有回”,每向上或向下移动都可以进行某些操作,而一次来回后就进行了许多操作。在分析摆盘子的过程时,可以将其分为一般情况与基层情况,基层情况就是盘子数量为1时的情况,此时移动次数显然为1;而一般情况呢?由于递归“调用自身”的特性,我们可以取巧,找到盘子个数为n,与盘子个数为n-1这两种不同情况下移动次数的关系。我们把移动n次看成3个过程:1、先移动n-1个盘子 2、将最下面那个最大的盘子移到另一个空柱子上 3、再移动n-1个盘子。经过递归过程分析,原本巨大的工作已经被分割为无数个小工作。
程序实现:经过过程分析,想必读者思路已经比较清晰了,那具体如何实现呢:对于递归,要明确3点:1、一般情况 2、基层情况 3、基层实现条件 本题基层情况就是n=1时移动次数为1;而一般情况就是Num(n)=2*Num(n-1)(由过程分析易得);至于基层实现条件那就比较容易推敲,就是n=1的时候。
具体代码:
int fun(int n)
{
if(n==1)
return 1;
else
return 2*fun(n-1)+1;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",fun(n));
}
简要总结:分析问题时首先对问题进行过程分析,对简单问题可以过程全面分析;对工作量大问题可以进行拆分,使之成为无数个小过程,递归就是如此,将问题本身大大简化;随后进行程序实现,将过程具体化为代码。