A Different Task

The (Three peg) Tower of Hanoi problem is a popular one in computer science. Briefly the problem is to transfer all the disks from peg-A to peg-C using peg-B as intermediate one in such a way that at no stage a larger disk is above a smaller disk. Normally, we want the minimum number of moves required for this task. The problem is used as an ideal example for learning recursion. It is so well studied that one can find the sequence of moves for smaller number of disks such as 3 or 4. A trivial computer program can find the case of large number of disks also.

Here we have made your task little bit difficult by making the problem more flexible. Here the disks can be in any peg initially.

If more than one disk is in a certain peg, then they will be in a valid arrangement (larger disk will not be on smaller ones). We will give you two such arrangements of disks. You will have to find out the minimum number of moves, which will transform the first arrangement into the second one. Of course you always have to maintain the constraint that smaller disks must be upon the larger ones.

Input

The input file contains at most 100 test cases. Each test case starts with a positive integer N ( 1N60), which means the number of disks. You will be given the arrangements in next two lines. Each arrangement will be represented by N integers, which are 12 or 3. If the i-th ( 1iN) integer is 1, you should consider that i-th disk is on Peg-A. Input is terminated by N = 0. This case should not be processed.

Output

Output of each test case should consist of a line starting with `Case #: ' where # is the test case number. It should be followed by the minimum number of moves as specified in the problem statement.

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

 题目大意:标准的汉诺塔上有n个大小各异的盘子。给定一个初始局面,求它到达给定目标局面至少需要多少步。

 输入格式:第一行为正整数n,第二行包含n个1-3的整数,即初始局面中每个盒子锁在的柱子编号;第三行和第二行格式相同,为目标局面。

 分析:考虑编号最大的盘子。如果这个盘子在初始局面和目标局面中位于同一根柱子上,那么根本不需要移动它,而如果移动了,反而不可能得到最优解。这样,我们可以在初始局面和目标局面中,找出所在柱子不同的盘子中编号最大的一个,设为k,那么k必须移动。

  让我们设想一下,移动k之前的一瞬间,柱子上的情况。假设盘子k需要从柱子1移动到柱子2.由于编号比k大的盘子不需要移动,而且也不会碍事,所以我们直接把他们看成不存在;编号比k小的盘子既不能在柱子1上,也不能在柱子2上,因此只能在柱子3上。换句话说,这时柱子1只有盘子k,柱子2为空,柱子3从上到下一次是盘子1,2,3,...k-1。我们把这个局面称为参考局面。

  由于盘子的移动是可逆的,根据对称性,我们只需要求出初始局面和目标局面移动成参考局面的步数之和,然后加1(移动盘子k)即可。换句话说,我们需要写一个函数f(P,i,final),表示已知各盘子的初始柱子编号数组为P(具体来说,P[i] 代表盘子 i 的柱子编号),把盘子1,2,3,...,i 全部移到柱子final所需的步数,则本题的答案就是  f(start,k-1,6-start[k]-finish[k])+f(finish,k-1,6-start[k]-finish[k])+1。其中start[i]和finish[i]是本题输入中盘子i的初始柱子和目标柱子,k是上面所说的“必须移动的编号最大的盘子”的编号。我们把柱子编号为1,2,3,所以“除了柱子x和柱子y之外的那个柱子”编号为6-x-y。

  如何计算f(P,i,final)?假设P[i]=final,那么f(P,i,final)=f(P,i-1,final);否则需要先把前i-1个盘子挪到6-P[i]-final这个盘子做中转,然后把盘子i移动到柱子final,最后吧前i-1个盘子从中转的柱子移动到目标柱子final。注意,最后一个步骤是把i-1个盘子从一个柱子整体移动到另一个柱子,根据汉诺塔问题的经典结论,这个步骤需要2i-1-1步,加上移动盘子 i 的那一步,一共需要2i-1步。换句话说,当P[i]不等于final的时候f(P,i,final)=f(P,i-1,6-P[i]-final)+2i-1

 代码如下:

 #include<cstdio>

 long long f(int* P, int i, int final) {
if(i == ) return ;
if(P[i] == final) return f(P, i-, final);
return f(P, i-, -P[i]-final) + (1LL << (i-));
} const int maxn = + ;
int n, start[maxn], finish[maxn]; int main() {
int kase = ;
while(scanf("%d", &n) == && n) {
for(int i = ; i <= n; i++) scanf("%d", &start[i]);
for(int i = ; i <= n; i++) scanf("%d", &finish[i]);
int k = n;
while(k >= && start[k] == finish[k]) k--; long long ans = ;
if(k >= ) {
int other = -start[k]-finish[k];
ans = f(start, k-, other) + f(finish, k-, other) + ;
}
printf("Case %d: %lld\n", ++kase, ans);
}
return ;
}

UVA 10795 A Different Task(汉诺塔 递归))的更多相关文章

  1. 数据结构--汉诺塔递归Java实现

    /*汉诺塔递归 * 1.将编号0-N-1个圆盘,从A塔座移动到B上面 * 2.将编号N的1个圆盘,从A移动到C上面 * 3.最后将B上面的N-1个圆盘移动到C上面 * 注意:盘子的编号从上到下1-N ...

  2. C++汉诺塔递归实现

    程序背景: 汉诺塔(Tower of Hanoi)又称河内塔,问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命 ...

  3. 化繁为简 经典的汉诺塔递归问题 in Java

    问题描述   在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑 ...

  4. Python之汉诺塔递归运算

    汉诺塔问题是一个经典的问题.汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆 ...

  5. c语言-汉诺塔递归调用

    #include<stdio.h> int main() { void hano_tower(int n,char one,char two,char three); int m=0; p ...

  6. C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)

    本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...

  7. 汉诺塔python3函数编写和过程分析

    !/usr/bin/env python3 -- coding: utf-8 -- 利用递归函数计算阶乘 N! = 1 * 2 * 3 * ... * N def fact(n): if n == 1 ...

  8. 杭电oj1995——汉诺塔V(java实现)

    正文之前,先说下做这题的心路历程(简直心累) 这是今天下午的第一道题 第一次看到题目标题——汉诺塔 内心OS:wc,汉诺塔诶,听名字就很难诶,没做过诶,肯定很难实现吧,不行,我得去看看讲解 然后就上b ...

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

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

随机推荐

  1. 如何使用Visual Studio 2013 创建Azure云应用

    创建 Azure 云服务 Azure 云服务包括执行应用程序所需操作的角色.当你将云服务发布到 Azure 时,每个角色将在云中的虚拟机上运行.有关如何开发 Azure 云服务的详细信息. 创建 Az ...

  2. deep learning(1)BP神经网络原理与练习

    具体原理参考如下讲义: 1.神经网络 2.反向传导 3.梯度检验与高级优化 看完材料1和2就可以梳理清楚bp神经网络的基本工作原理,下面通过一个C语言实现的程序来练习这个算法 //Backpropag ...

  3. Weka 入门2

    现在我们介绍使用Weka来对数据进行分类.对数据进行分类,我们必须先指定那一列作为预测类别.因为数据文件格式的问题,类别一般都是最后一列属性.我们可以使用setClassIndex来设置类别.然后我们 ...

  4. HW4.43

    import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...

  5. POJ-1177 Picture 矩形覆盖周长并

    题目链接:http://poj.org/problem?id=1177 比矩形面积并麻烦点,需要更新竖边的条数(平行于x轴扫描)..求横边的时候,保存上一个结果,加上当前长度与上一个结果差的绝对值就行 ...

  6. oracle 表空管理方式(LMT)、ASSM段管理方式、一级位图块、二级位图块、三级位图块。

    今天是2013-12-16,今天和明天是我学习oracle生涯中一个特殊的日子.今天晚上进行了一下表空间管理方式的学习,在此记录一下笔记. 对于oracle数据库最小i/0单位是数据块,最想分配空间单 ...

  7. 如何获取web中某个元素的id

    1.在原始的web界面上,切换到开发者模式,一般都有快捷键,本机的快捷键为(Ctrl+shift+I) 2.在开发者模式界面的左上角有一个放大镜的工具,点击一下,再去界面中找相应的元素,之后就可以定位 ...

  8. Dom4J对XML的创建、修改、删除等操作

    Dom4j也可以很方便完成XML文档的创建.元素的修改.文档的查询遍历等,但dom4j稍比jdom复杂一点,不过在大片文档的情况下dom4j的性能要不jdom好. # 准备 首先,提供相关的jar包 ...

  9. fastjson对Date的处理

    对日期的序列化: 一种方法是通过注解 Java代码 ? 1 2 @JSONField (format="yyyy-MM-dd HH:mm:ss")   public Date bi ...

  10. iOS 使用CLGeocoder获取地理位置

    placemark(MKPlacemark类的对象)其实是geocoder(MKReverseGeocoder类的对象)的一个属性.从geocoder里面取placemark这个和直接取placema ...