zoukankan      html  css  js  c++  java
  • LintCode 汉诺塔

    题目链接:https://www.lintcode.com/problem/tower-of-hanoi/description

    题目大意

      经典递归问题。

    分析

      由于是经典问题了,这里不讨论用递归实现,也不讨论用栈模拟实现,只讨论纯迭代实现。
      首先用 L, M, R 来标记左柱子,中柱子,右柱子。
      我们知道汉诺塔问题与二进制是密不可分的,“n-圆盘汉诺塔问题”最少只需要$2^n - 1$步,而且如果 n 为奇数,第一步必然是 L->R;如果 n 为偶数,第一步必然是 L->M。
      现在我们定义三个操作,每个操作相当于走一步:
    1. 把 M 标记和 R 标记互换,执行 L->R。
    2. 把 L 标记和 M 标记互换,执行 L->R。
    3. 把 L 标记和 M 标记互换,把 M 标记和 R 标记互换,执行 L->R。

      于是这个问题可以这样解决,去掉第一步,还剩$2^n - 2$步,如果我们把走两步算作一大步,那么还剩$2^{n - 1} - 1$大步,我们令$i:1 ightarrow2^{n - 1} - 1$依次模拟每个大步,如果 i 的最低 2 进制位的位置是偶数位置时,就执行 2 次操作 3,否则执行 1 次操作 1 和 1 次操作 2。

      神奇的是,这样做居然是可行的。

      PS:我是不知道为啥,我是闲着无聊找规律找到的。

    代码如下

     1 class Solution {
     2 public:
     3     string L = "A", M = "B", R = "C";
     4     vector< string > ans;
     5     /**
     6      * @param n: the number of disks
     7      * @return: the order of moves
     8      */
     9     vector<string> towerOfHanoi(int n) {
    10         if(n % 2 == 0) swap(M, R);
    11         ans.push_back(step(L, R));
    12         
    13         n = (((1 << n) - 2) >> 1);
    14         for(int i = 1; i <= n; ++i) {
    15             // 如果i的最低2进制位的位置是偶数,就执行2次操作3,否则执行1次操作1和一次操作2
    16             if(__builtin_ffs(i) % 2 == 0) {
    17                 op3();
    18                 op3();
    19             }
    20             else {
    21                 op1();
    22                 op2();
    23             }
    24         }
    25         
    26         return ans;
    27     }
    28     
    29     inline string step(string x, string y) {
    30         return "from " + x + " to " + y;
    31     }
    32     
    33     inline void op1() {
    34         swap(M, R); 
    35         ans.push_back(step(L, R));
    36     }
    37     
    38     inline void op2() {
    39         swap(L, M);
    40         ans.push_back(step(L, R));
    41     }
    42     
    43     inline void op3() {
    44         swap(M, L); swap(R, M); 
    45         ans.push_back(step(L, R));
    46     }
    47 };
    View Code
  • 相关阅读:
    流水线操作verilog
    16x16移位相加乘法器verilog实现
    Nios II对flash进行读写(DE2)
    initial使用的要点
    边沿检测电路设计verilog
    DDoS攻防战 (四):CC攻击防御系统部署
    DDoS攻防战(三):ip黑白名单防火墙frdev的原理与实现
    DDoS攻防战 (二) :CC攻击工具实现与防御理论
    DDoS攻防战 (一) : 概述
    IP流量重放与pcap文件格式解析
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/11341166.html
Copyright © 2011-2022 走看看