zoukankan      html  css  js  c++  java
  • 用栈模拟汉诺塔问题

    在经典的汉诺塔问题中,有 3 个塔和 N 个可用来堆砌成塔的不同大小的盘子。要求盘子必须按照从小到大的顺序从上往下堆 (如,任意一个盘子,其必须堆在比它大的盘子上面)。同时,你必须满足以下限制条件:

    (1) 每次只能移动一个盘子。
    (2) 每个盘子从堆的顶部被移动后,只能置放于下一个堆中。
    (3) 每个盘子只能放在比它大的盘子上面。

    请写一段程序,实现将第一个堆的盘子移动到最后一个堆中。

    分析:

    (1)n == 1

                 第1次  1号盘  A---->C       sum = 1 次

           (2)  n == 2

                 第1次  1号盘  A---->B

                 第2次  2号盘  A---->C

                 第3次  1号盘  B---->C        sum = 3 次

      (3)n == 3

            第1次  1号盘  A---->C

            第2次  2号盘  A---->B

            第3次  1号盘  C---->B

            第4次  3号盘  A---->C

            第5次  1号盘  B---->A

            第6次  2号盘  B---->C

            第7次  1号盘  A---->C        sum = 7 次

    设栈A上最初的盘子总数为n,

    当n=1时,只要将编号为1的盘子从栈A直接移到栈C上即可;否则执行以下三步:

    (1)用栈C做过渡,将栈A上的n-1个盘子移到栈B上;

    (2)将栈A上的最后一个盘子直接移到栈C上面;

    (3)用栈A做过渡,将栈B上面的n-1个盘子移到栈C上面;

    根据这种解法,如何将n-1个盘子从一个栈移到另一个栈的问题是一个和原问题具有相同特征属性的问题,只是问题的规模-1,因此可以用相同的方法求解。

      1 <?php
      2 header("Content-type: text/html; charset=utf-8");
      3 class Stack
      4 {
      5     private $id = null;//栈的标识,用于区分从哪个栈移到哪个栈
      6     private $top = -1;//栈顶
      7     private $max_size = 100;//栈的最大容量
      8     private $stack = array();
      9     
     10     public function __construct($id)
     11     {
     12         $this->id = $id;
     13     }
     14     
     15     public function get_id()
     16     {
     17         return $this->id;
     18     }
     19     
     20     /**
     21      * 入栈
     22      */
     23     public function push($val)
     24     {
     25         if($this->top == $this->max_size-1)
     26         {
     27             return false;//栈满
     28         }
     29         $this->top++;
     30         $this->stack[$this->top] = $val;
     31     }
     32     
     33     /**
     34      * 出栈
     35      */
     36     public function pop()
     37     {
     38         if($this->top == -1)
     39         {
     40             return false;//栈空
     41         }
     42         $val = $this->stack[$this->top];
     43         unset($this->stack[$this->top]);
     44         $this->top--;
     45         return $val;
     46     }
     47 }
     48 
     49 /**
     50  * 将栈A上的n个盘子移动到栈C上面,栈B用作辅助
     51  */
     52 function hanoi($n, $stack_a, $stack_b, $stack_c)
     53 {
     54     if($n == 1)//只有一个盘子时,直接移动到目标栈
     55     {
     56         move($stack_a, $stack_c);
     57     } else {
     58         hanoi($n-1, $stack_a, $stack_c, $stack_b);//将栈A上编号为1至n-1个盘子移到栈B上,栈C作为辅助
     59         move($stack_a, $stack_c);//将编号为n的盘子从栈A移到C
     60         hanoi($n-1, $stack_b, $stack_a, $stack_c);//将栈B上编号为1至n-1个盘子移到栈C上,栈A作为辅助
     61     }
     62 }
     63 
     64 /**
     65  * 移动
     66  */
     67 function move($stack_a, $stack_c)
     68 {
     69     static $count = 0;//盘子移动的次数
     70     $val = $stack_a->pop();
     71     $stack_c->push($val);
     72     $count++;
     73     echo $count . ": 从栈" . $stack_a->get_id() . "把" . $val . "移到栈" . $stack_c->get_id() . "<br/>"; 
     74 }
     75 
     76 /**
     77  * 递归解法($n: 表示有多少个盘子)
     78  * 1.先创建3个栈,并初始化栈A
     79  * 2.将栈A上的n个盘子移动到栈C上面,栈B用作辅助
     80  * 3.打印盘子的移动轨迹
     81  */
     82 function solution($n = 3)
     83 {
     84     $A = new Stack('A');
     85     $B = new Stack('B');
     86     $C = new Stack('C');
     87     for($i=$n;$i>0;$i--)
     88     {
     89         $A->push($i);
     90     }
     91     
     92     hanoi($n, $A, $B, $C);
     93     
     94     //打印盘子的移动轨迹
     95     echo "<pre>";
     96     print_r($A);
     97     print_r($B);
     98     print_r($C);
     99     die;
    100 }
    101 
    102 solution(4);
  • 相关阅读:
    ajax收藏
    excel提取文本格式时分秒中数字的方法并计算成秒的公式
    vi编辑模式中按方向键变ABCD的解决方法
    IIS配置Url重写实现http自动跳转https的重定向方法
    IIS中启用目录浏览功能后不能下载未知扩展名文件的解决方法
    Nginx禁止IP访问,只允许域名访问
    nginx在Window平台http自动跳转https设置方法
    通过清理注册表方式清理window远程连接的历史记录
    DOS批处理添加IP域名,备份与恢复
    windows修改snmp端口号方法
  • 原文地址:https://www.cnblogs.com/573583868wuy/p/9357259.html
Copyright © 2011-2022 走看看