zoukankan      html  css  js  c++  java
  • 汉诺塔问题递归算法分析

    转自:http://www.cnblogs.com/zhangqqqf/archive/2008/09/12/1289730.html

    一个庙里有三个柱子,第一个有64个盘子,从上往下盘子越来越大。要求庙里的老和尚把这64个盘子全部移动到第三个柱子上。移动的时候始终只能小盘子压着大盘子。而且每次只能移动一个。

      1、此时老和尚(后面我们叫他第一个和尚)觉得很难,所以他想:要是有一个人能把前63个盘子先移动到第二个柱子上,我再把最后一个盘子直接移动到第三个柱子,再让那个人把刚才的前63个盘子从第二个柱子上移动到第三个柱子上,我的任务就完成了,简单。所以他找了比他年轻的和尚(后面我们叫他第二个和尚),命令:

              ① 你丫把前63个盘子移动到第二柱子上

              ② 然后我自己把第64个盘子移动到第三个柱子上后

              ③ 你把前63个盘子移动到第三柱子上

          2、第二个和尚接了任务,也觉得很难,所以他也和第一个和尚一样想:要是有一个人能把前62个盘子先移动到第三个柱子上,我再把最后一个盘子直接移动到第二个柱子,再让那个人把刚才的前62个盘子从第三个柱子上移动到第二个柱子上,我的任务就完成了,简单。所以他也找了比他年轻的和尚(后面我们叫他第三和尚),命令:

              ① 你把前62个盘子移动到第三柱子上

              ② 然后我自己把第63个盘子移动到第二个柱子上后

              ③ 你把前62个盘子移动到第二柱子上

      3、第三个和尚接了任务,又把移动前61个盘子的任务依葫芦话瓢的交给了第四个和尚,等等递推下去,直到把任务交给了第64个和尚为止(估计第64个和尚很郁闷,没机会也命令下别人,因为到他这里盘子已经只有一个了)。

      4、到此任务下交完成,到各司其职完成的时候了。完成回推了:

    第64个和尚移动第1个盘子,把它移开,然后第63个和尚移动他给自己分配的第2个盘子。
    第64个和尚再把第1个盘子移动到第2个盘子上。到这里第64个和尚的任务完成,第63个和尚完成了第62个和尚交给他的任务的第一步。

      从上面可以看出,只有第64个和尚的任务完成了,第63个和尚的任务才能完成,只有第2个和尚----第64个和尚的任务完成后,第1个和尚的任务才能完成。这是一个典型的递归问题。 现在我们以有3个盘子来分析:

    第1个和尚命令:

              ① 第2个和尚你先把第一柱子前2个盘子移动到第二柱子。(借助第三个柱子)

              ② 第1个和尚我自己把第一柱子最后的盘子移动到第三柱子。

              ③ 第2个和尚你把前2个盘子从第二柱子移动到第三柱子。

       很显然,第二步很容易实现(哎,人总是自私地,把简单留给自己,困难的给别人)。

    其中第一步,第2个和尚他有2个盘子,他就命令:

              ① 第3个和尚你把第一柱子第1个盘子移动到第三柱子。(借助第二柱子)

              ② 第2个和尚我自己把第一柱子第2个盘子移动到第二柱子上。

              ③ 第3个和尚你把第1个盘子从第三柱子移动到第二柱子。

       同样,第二步很容易实现,但第3个和尚他只需要移动1个盘子,所以他也不用在下派任务了。(注意:这就是停止递归的条件,也叫边界值)

    第三步可以分解为,第2个和尚还是有2个盘子,命令:

              ① 第3个和尚你把第二柱子上的第1个盘子移动到第一柱子。

              ② 第2个和尚我把第2个盘子从第二柱子移动到第三柱子。

              ③ 第3个和尚你把第一柱子上的盘子移动到第三柱子。
                       
    分析组合起来就是:1→3 1→2 3→2 借助第三个柱子移动到第二个柱子 |1→3 自私人留给自己的活| 2→1 2→3 1→3借助第一个柱子移动到第三个柱子|共需要七步。

    如果是4个盘子,则第一个和尚的命令中第1步和第3步各有3个盘子,所以各需要7步,共14步,再加上第1个和尚的1步,所以4个盘子总共需要移动7+1+7=15步,同样,5个盘子需要15+1+15=31步,6个盘子需要31+1+31=64步……由此可以知道,移动n个盘子需要(2的n次方)-1步。

       从上面整体综合分析可知把n个盘子从1座(相当第一柱子)移到3座(相当第三柱子):

    (1)把1座上(n-1)个盘子借助3座移到2座。
    (2)把1座上第n个盘子移动3座。
    (3)把2座上(n-1)个盘子借助1座移动3座。

    下面用hanoi(n,a,b,c)表示把1座n个盘子借助2座移动到3座。

           (1)hanoi(n-1,1,3,2)

         (2)move(n,1,3) 
                  (3)步上是 hanoi(n-1,2,1,3)
    用C语言表示出来,就是:
    #include <stdio.h>
    int move(int n,char a, char b)
    {
         printf("number..%d..form..%c..to..%c.."n",n,a,b);
         return 0;
    }
    int hanoi(int n,char a,char b,char c)
    {
         if( n==1 ) move (1,a,c);
         else
              {
                   hanoi(n-1,a,c,b);
                   move(n,a,c);
                   hanoi(n-1,b,a,c);
              };
         return 0;
    }
    int main()
    {
         int num;
         scanf("%d",&num);
         hanoi(num,'A','B','C');
         return 0;
    }

    祝你早日攒够失望,然后开始新的生活。
  • 相关阅读:
    PATA 1071 Speech Patterns.
    PATA 1027 Colors In Mars
    PATB 1038. 统计同成绩学生(20)
    1036. 跟奥巴马一起编程(15)
    PATA 1036. Boys vs Girls (25)
    PATA 1006. Sign In and Sign Out (25)
    读取web工程目录之外的图片并显示
    DOS命令
    java连接oracle集群
    servlet
  • 原文地址:https://www.cnblogs.com/LuRenJiang/p/6915904.html
Copyright © 2011-2022 走看看