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
  • 相关阅读:
    ansible become与sudo
    GTID 复制、主从不一致跳过操作、快速切换master
    percona toolkit 更新至一致性检查
    oracle ldap (ODEE ODCC)复制概要
    zabbix api 批量添加主机(python3 requests)
    grafana 5.0+ templating变化
    redis sentinel 客户端
    centos7 变更默认mariadb 记录
    python3 float 计算
    企业微信开发记录
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/11341166.html
Copyright © 2011-2022 走看看