题目链接: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\rightarrow2^{n - 1} - 1$依次模拟每个大步,如果 i 的最低 2 进制位的位置是偶数位置时,就执行 2 次操作 3,否则执行 1 次操作 1 和 1 次操作 2。

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

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

代码如下

 class Solution {
public:
string L = "A", M = "B", R = "C";
vector< string > ans;
/**
* @param n: the number of disks
* @return: the order of moves
*/
vector<string> towerOfHanoi(int n) {
if(n % == ) swap(M, R);
ans.push_back(step(L, R)); n = ((( << n) - ) >> );
for(int i = ; i <= n; ++i) {
// 如果i的最低2进制位的位置是偶数,就执行2次操作3,否则执行1次操作1和一次操作2
if(__builtin_ffs(i) % == ) {
op3();
op3();
}
else {
op1();
op2();
}
} return ans;
} inline string step(string x, string y) {
return "from " + x + " to " + y;
} inline void op1() {
swap(M, R);
ans.push_back(step(L, R));
} inline void op2() {
swap(L, M);
ans.push_back(step(L, R));
} inline void op3() {
swap(M, L); swap(R, M);
ans.push_back(step(L, R));
}
};

LintCode 汉诺塔的更多相关文章

  1. 【LintCode·容易】用栈模拟汉诺塔问题

    用栈模拟汉诺塔问题 描述 在经典的汉诺塔问题中,有 3 个塔和 N 个可用来堆砌成塔的不同大小的盘子.要求盘子必须按照从小到大的顺序从上往下堆 (如:任意一个盘子,其必须堆在比它大的盘子上面).同时, ...

  2. 算法笔记_013:汉诺塔问题(Java递归法和非递归法)

    目录 1 问题描述 2 解决方案  2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...

  3. C#递归解决汉诺塔问题(Hanoi)

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace MyExamp ...

  4. 数据结构0103汉诺塔&八皇后

    主要是从汉诺塔及八皇后问题体会递归算法. 汉诺塔: #include <stdio.h> void move(int n, char x,char y, char z){ if(1==n) ...

  5. Conquer and Divide经典例子之汉诺塔问题

    递归是许多经典算法的backbone, 是一种常用的高效的编程策略.简单的几行代码就能把一团遭的问题迎刃而解.这篇博客主要通过解决汉诺塔问题来理解递归的精髓. 汉诺塔问题简介: 在印度,有这么一个古老 ...

  6. 几年前做家教写的C教程(之四专讲了指针与汉诺塔问题)

    C语言学习宝典(4) 指针:可以有效的表示复杂的数据结构,能动态的分配动态空间,方便的使用字符串,有效的使用数组,能直接处理内存单元 不掌握指针就没有掌握C语言的精华 地址:系统为每一个变量分配一个内 ...

  7. python实现汉诺塔

    经典递归算法汉诺塔分析: 当A柱子只有1个盘子,直接A --> C 当A柱子上有3个盘子,A上第一个盘子 --> B, A上最后一个盘子 --> C, B上所有盘子(1个) --&g ...

  8. fzu1036四塔问题(汉诺塔问题拓展)

    #include<iostream> #include<cstdio> #include<cmath> using namespace std; ]; int ru ...

  9. 1019: [SHOI2008]汉诺塔

    1019: [SHOI2008]汉诺塔 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1495  Solved: 916[Submit][Status] ...

随机推荐

  1. javsscript闭包的一种使用场景--沙箱

    ​ //沙箱:模块化,沙箱是一个隔离的环境,最大的好处就是避免全局变量的污染. var model = (function () {//一个匿名的立即执行函数 var price = 900;//这是 ...

  2. PAT_A1100#Mars Numbers

    Source: PAT A1100 Mars Numbers (20 分) Description: People on Mars count their numbers with base 13: ...

  3. JVM系列文章合集

    博客作者:纯洁的微笑 JVM系列(①):java类的加载机制 JVM系列(②):JVM内存结构 JVM系列(③):GC算法 垃圾收集器 JVM系列(④):jvm调优-命令大全(jps jstat jm ...

  4. 【webpack】webpack之postcss-loader的基本使用---【巷子】

    一.postcss-loader简介 postcss-loader 用来对.css 文件进行处理,并添加在 style-loader 和 css-loader 之后.通过一个额外的 postcss 方 ...

  5. PHP上传文件超过文件最大限制导致无法上传成功

    最近在学习<HeadFirst PHP & MySQL>一书的第5章"使用存储在文件中的数据",做一个文件上传的应用时,出现了错误,就是文件无法成功上传.这个问 ...

  6. uvloop官网翻译

    魔术堆栈 uvloop:快速的Python网络连接 作者Yury Selivanov @ 1st1 2016年5月3日 TL; DR asyncio是Python标准库附带的异步I / O框架.在此博 ...

  7. 四、hibernate的缓存

    缓存: 就是将数据保存到内存中,需要使用时直接从内存中获取,不需要每次查询数据库或者磁盘中的文件 hibernate的缓存 一级缓存:Session级别的缓存 二级缓存:SessionFactory级 ...

  8. Shell内置命令——declare

  9. teb教程4

    障碍物避障以及机器人足迹模型 简介:障碍物避障的实现,以及必要参数的设置对于机器人足迹模型和其对应的影响 1.障碍物避障是怎样工作的 1.1 惩罚项 障碍物避障作为整个路径优化的一部分.显然,优化是找 ...

  10. JDBC getConnection细节

    https://blog.csdn.net/luanlouis/article/details/29850811 概述             一般情况下,在应用程序中进行数据库连接,调用JDBC接口 ...