• 题目介绍:

标准的汉诺塔上有n个大小各异的盘子。现给定一个初始局面(见图1),求它到目标局面(见图2)至少需要移动多少步?

移动规则:一次只能移动一个盘子;且在移动盘子之前,必须把压在上面的其他盘子先移走;基于汉诺塔问题的原始约定,编号大的盘子不得压在编号小的盘子上。

Sample Input

3

1 1 1

2 2 2

3

1 2 3

3 2 1

4

1 1 1 1

1 1 1 1

0

Sample Output

Case 1: 7

Case 2: 3

Case 3: 0

  • 问题分析:

为了更好的剖析问题。我们首先考虑编号最大的盘子。显然,如果这个盘子的在初始局面和目标局面中位于同一根柱子,那么我们可以根本不需要移动它。直接忽略它在两个局面的存在。

设现在存在初始局面跟目标局面中位置不同的盘子最大编号为k。现在设想一下移动k之前的瞬间。不妨假设盘子k需要从柱子A移动到柱子B,那么在移动k之前的局面必然是,1,2,...k-1全部位于柱子C,而且从上到下排好序。我们把这个局面称为参考局面。

根据对称性,我们只需要求出初始局面和目标局面到参考局面移动的步数之和,再加上1(移动编号为k的盘子)即可。

现定义这样的一个函数 f(arr,k,flag):表示已知各盘子的初始编号为数组arr,把1,2,...,k移动到flag柱子所需要的最少步数。可得本题答案表示如下:

ans = f(start,k-1,6-start[k]-finish[kl) + f(finish,k-1,6-start[k]-finish[kl) + 1;

将问题分解之后,我们再考虑如何基于汉诺塔的性质,递归求解f(arr,k,flag)。

显然,k=0时意味着没有盘子需要移动,此时返回0,作为递归跳出的判断条件;

K!=0时,比较arr[k]==flag? 如果相等,那么很好办,直接f(arr,k,flag) = f(arr,k-1,flag)即可,因为编号k不需要移动。当arr[k]!=flag时就需要推导一下了。我们把“1,2,...,k-1”看做一个整体,此时移动k前后需要将整体从一个柱子移动到另一个柱子,而根据汉诺塔的经典理论,将n个盘子初始有序的盘子由一个柱子移动到另一个柱子最少需要:2^n - 1 次。本题中,我们还要加上移动盘子k的一次操作,故最后:

f(arr,k,flag) = f(arr,k-1,6-arr[k]-flag)  +  (1<<(k-1))

  • 参考代码:

 #include <cstdio>

 typedef long long ll;

 const int maxn=;

 int a[maxn],b[maxn];

 ll f(int *a,int k,int flag){

     if(k<) return ;

     else if(a[k]==flag){

         return f(a,k-,flag);

     }else{

         return f(a,k-,-a[k]-flag) + (1LL<<(k-));    //"1LL"自动转换为long long 类型

     }

 }

 int main(){

     int n,t=;

     while(scanf("%d",&n)== && n){

         for(int i=;i<=n;i++) scanf("%d",&a[i]);

         for(int i=;i<=n;i++) scanf("%d",&b[i]);

         //find 'k'

         int k=n;

         while(a[k]==b[k] && k>=)k--;

         ll ans=;

         ans = f(a,k-,-a[k]-b[k]) + f(b,k-,-a[k]-b[k]) + ;

         if(k==) ans = ;

         printf("Case %d: %lld\n",t++,ans);

     }

     return ;

 }

结语:

这道题从刚开始入手的杂乱通过一步步转换推导之后,最终程序的精简实现不由得让人拍案叫绝!本文解析或许词不达意,不到之处请谅解。同时,欢迎有其他思路或想法的朋友私下交流讨论。

(hint:提交本题目时注意数据类型选用64位整型数long long,”(1<<(k-1))”若没有加上“LL”则提交结果为WA! )

新版汉诺塔(UVa10795 - A Different Task)的更多相关文章

  1. UVA 10795 A Different Task(汉诺塔 递归))

    A Different Task The (Three peg) Tower of Hanoi problem is a popular one in computer science. Briefl ...

  2. 【汉诺塔问题】UVa 10795 - A Different Task

    [经典汉诺塔问题] 汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A.B.C,A座上有64个盘子,盘子大小不等,大的在下,小的在上.有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动 ...

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

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

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

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

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

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

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

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

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

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

  8. python实现汉诺塔

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

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

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

随机推荐

  1. TextView和EditText中的setFilters方法说明

    在TextView中有一个方法public void setFilters(InputFilter[] filters),API中有一句说明:Sets the list of input filter ...

  2. android studio 中 .9.png的制作

    折腾好久,最后在一个群里面咨询一个朋友才弄好的,用的是1.2.2版,感觉对.9的支持不太好, 1,用一张干净的png图片放在mipmap里面. 2,点击图片右键最后一项,create 9-patch ...

  3. BZOJ 2005: [Noi2010]能量采集

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 3312  Solved: 1971[Submit][Statu ...

  4. flask01 安装及初涉

    一.安装 1.pip的安装 $ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py $ python get-pip.p ...

  5. 匹配字符串的KMP算法

    其中next序列,表示子串的前后缀最大匹配长度. 例如对于字符串C[], next[i]表示子串c[0 .. i]中, 前缀与后缀的最大匹配长度. 举例如果子串是 abcuab, 其前缀是a, ab, ...

  6. Apache Rewrite 拟静态配置

    1.mod_rewrite 简介和配置 Rewirte主要的功能就是实现URL的跳转和隐藏真实地址,基于Perl语言的正则表达式规范.平时帮助我们实现拟静态,拟目录,域名跳转,防止盗链等 2.mod_ ...

  7. 设置select默认值

    W3C下设置一个默认值直接为 select.value='默认值'. IE8下设置默认值必须有这个option才能被设置,不像W3C 如chrome这种,直接设置就能显示,如果IE下这样设置的话sel ...

  8. 用微信小程序做H5游戏尝试

    微信小程序发布后,公司虽然没有拿到第一批内测资格,但作为微信亲密合作伙伴,一定要第一时间去尝试啦.现在微信小程序刚发布还在测试阶段,可以说是1.0版本,所以框架和结构内容都还不多,相关的文档跟微信AP ...

  9. FPGA中的INOUT接口和高阻态

    除了输入输出端口,FPGA中还有另一种端口叫做inout端口.如果需要进行全双工通信,是需要两条信道的,也就是说需要使用两个FPGA管脚和外部器件连接.但是,有时候半双工通信就能满足我们的要求,理论上 ...

  10. 记一次ASP.NET网站的入侵和如何避免被入侵

    ASP.NET网站入侵第二波(LeaRun.信息化快速开发框架 已被笔者拿下) 详细介绍请看第二波 首先我要申明的是不是什么语言写出来的程序就不安全,而是得看写代码的人如何去写这个程序 前些日子我去客 ...