题目链接: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. form表单submit事件

    form表单submit事件同时会触发form表单中button按钮的click事件 <!DOCTYPE html> <html> <head> <meta ...

  2. [STemWin教程入门篇] 第一期:emWin介绍

    转自:http://bbs.armfly.com/read.php?tid=1544 SEGGER公司介绍 了解emWin之前,先了解一下SEGGER这家公司,了解生产商才能对emWin有更加全面的认 ...

  3. cesium默认全屏按钮自定义

    cesium默认全屏按钮自定义 1  隐藏默认的svg 2  修改它默认的按钮边框,背景 3   修改它点击时的样式 代码如下: .cesium-viewer-fullscreenContainer ...

  4. 在JMeter测试计划中如何控制业务比例

    作者:Selingchen 来源:CSDN 原文:https://blog.csdn.net/selingchen/article/details/47844375

  5. docker stack利用secrets启动wordpress

    docker-compose文件 version: '3.1' services: web: image: wordpress ports: - : secrets: - my-pw environm ...

  6. js事件处理程序详解,html事件处理程序,dom0级事件处理程序,dom2级事件处理程序

    博客搬迁,给你带来的不便,敬请谅解! http://www.suanliutudousi.com/2017/11/24/js%e4%ba%8b%e4%bb%b6%e5%a4%84%e7%90%86%e ...

  7. Nodejs入门级基础+实战

    这篇随笔将会按序记录如下内容: NodeJs 简介 安装  NodeJs HTTP 模块.URL 模块 CommonJs 和 Nodejs 中自定义模块 NodeJs FS 模块 利用 HTTP 模块 ...

  8. HTML + CSS (下)【更新中】

    弹性盒子: 定义:弹性盒子模型是css3中新提出的一种布局方案.是一种为了应对针对不同屏幕宽度不同设备的一整套新的布局方案. 主要是对一个容器中的子元素进行排列.对齐和分配空白空间的方案的调整. 新旧 ...

  9. JS判断浏览器类型的方法总结(IE firefox chrome opera safari)

    JS判断浏览器类型的方法总结,可判别当前客户端所使用的浏览器是ie,firefox,safari,chrome或者是opera,另外js可以精确判断到ie浏览器的版本,依然直接上代码,需要的朋友可按照 ...

  10. throws/throw Exception 异常应用

    throws通常用于方法的声明,当方法中发生异常的时候,却不想在方法中对异常进行处理的时候,就可以在声明方法时, 使用throws声明抛出的异常,然后再调用该方法的其他方法中对异常进行处理(如使用tr ...