【汉诺塔问题】UVa 10795 - A Different Task
【经典汉诺塔问题】
汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求打印移动的步骤。如果只有一个盘子,则不需要利用B座,直接将盘子从A移动到C。
- 如果有2个盘子,可以先将盘子1上的盘子2移动到B;将盘子1移动到c;将盘子2移动到c。这说明了:可以借助B将2个盘子从A移动到C,当然,也可以借助C将2个盘子从A移动到B。
- 如果有3个盘子,那么根据2个盘子的结论,可以借助c将盘子1上的两个盘子从A移动到B;将盘子1从A移动到C,A变成空座;借助A座,将B上的两个盘子移动到C。这说明:可以借助一个空座,将3个盘子从一个座移动到另一个。
- 如果有4个盘子,那么首先借助空座C,将盘子1上的三个盘子从A移动到B;将盘子1移动到C,A变成空座;借助空座A,将B座上的三个盘子移动到C。
即:f(n)=f(n-1)+1+f(n-1)=(2^n)-1; f(1)=1;
代码如下:
#include <iostream>
#include <cstdio>
using namespace std; int step = ;
void move ( char sour, char dest )
{
printf ( "move from %c to %c \n", sour, dest);
}
void hanoi ( int n, char sour, char temp, char dest )
{
if (n == )
{
move (sour, dest);
++step;
}
else
{
hanoi ( n-, sour, dest, temp );
move (sour,dest);
++step;
hanoi ( n-, temp, sour, dest );
}
}
int main ()
{
int n = ;
hanoi ( n, 'A', 'B', 'C' );
printf ( "Total steps is %d\n", step );
return ;
}
【新汉诺塔问题】
给定初始局面和目标局面,求从初始局面到目标局面至少需要多少步。
分析:
- 参考局面:待移动盘子k在其初始柱子上且k上无其他盘子,k的目标柱子为空,中间柱子从上到下依次为1,2,...,k-1盘子。
- 首先找不在目标柱子上最大的盘子k,因为如果最大的盘子在目标柱子上它不需要移动,也不碍事。
- 剩下的任务与经典汉诺塔问题类似,即将k-1个盘子移到参考局面;将盘子k移到目标柱子;再将k-1个盘子移到目标局面(因移动是可逆的,故可看做是将目标局面的盘子移到参考局面)。可以看出这是个递归问题。
即我们需要一个函数f(P, i, final) : 将编号为1~i的盘子全部移到柱子final上所需要的步数(数组P表示各盘子的初始柱子编号,除去盘子的初始柱子x和最终柱子y剩下的那根柱子编号为6-x-y,因为只有柱子1,2,3);
则:ans = f(start,k-1,6-start[k]-finish[k])+f(finish,k-1,6-start[k]-finish[k])+1;
至于函数f的计算,当i为0时,无需移动;否则将1~i-1的盘子全部移到参考局面。若i-1号盘子本身在中转柱子上,那么就等同于只移动1~i-2号盘子到final柱子上。移动1~i-1号盘子由参考局面到目标局面的过程即为经典汉诺塔过程,步数为2^(i-1)-1;此处注意答案要用long long;
代码如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int maxn = ;
int n, A[maxn], B[maxn];
//f(P, i, final) : 将编号为1~i的盘子全部移到柱子final上所需要的步数
//(数组P表示各盘子的初始柱子编号,除去盘子的初始柱子x和最终柱子y剩下的那根柱子编号为6-x-y)
long long f(int* P, int i, int fin)
{
if(!i) return ;
if(P[i] == fin) return f(P, i-, fin);
return f(P, i-, -P[i]-fin) + + ((1LL << (i-)) - );
}
int main()
{
int kase = ;
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]);
}
int k = n;
while(k && A[k] == B[k]) k--; long long ans = ;
if(k >= )
{
int tmp = -A[k]-B[k];
ans = f(A, k-, tmp) + + f(B, k-, tmp);
}
printf("Case %d: %lld\n", ++kase, ans);
}
return ;
}
【汉诺塔问题】UVa 10795 - A Different Task的更多相关文章
- UVA 10795 A Different Task(汉诺塔 递归))
A Different Task The (Three peg) Tower of Hanoi problem is a popular one in computer science. Briefl ...
- UVA 10254 - The Priest Mathematician (dp | 汉诺塔 | 找规律 | 大数)
本文出自 http://blog.csdn.net/shuangde800 题目点击打开链接 题意: 汉诺塔游戏请看 百度百科 正常的汉诺塔游戏是只有3个柱子,并且如果有n个圆盘,至少需要2^n- ...
- 算法笔记_013:汉诺塔问题(Java递归法和非递归法)
目录 1 问题描述 2 解决方案 2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...
- C#递归解决汉诺塔问题(Hanoi)
using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace MyExamp ...
- 数据结构0103汉诺塔&八皇后
主要是从汉诺塔及八皇后问题体会递归算法. 汉诺塔: #include <stdio.h> void move(int n, char x,char y, char z){ if(1==n) ...
- Conquer and Divide经典例子之汉诺塔问题
递归是许多经典算法的backbone, 是一种常用的高效的编程策略.简单的几行代码就能把一团遭的问题迎刃而解.这篇博客主要通过解决汉诺塔问题来理解递归的精髓. 汉诺塔问题简介: 在印度,有这么一个古老 ...
- 几年前做家教写的C教程(之四专讲了指针与汉诺塔问题)
C语言学习宝典(4) 指针:可以有效的表示复杂的数据结构,能动态的分配动态空间,方便的使用字符串,有效的使用数组,能直接处理内存单元 不掌握指针就没有掌握C语言的精华 地址:系统为每一个变量分配一个内 ...
- python实现汉诺塔
经典递归算法汉诺塔分析: 当A柱子只有1个盘子,直接A --> C 当A柱子上有3个盘子,A上第一个盘子 --> B, A上最后一个盘子 --> C, B上所有盘子(1个) --&g ...
- fzu1036四塔问题(汉诺塔问题拓展)
#include<iostream> #include<cstdio> #include<cmath> using namespace std; ]; int ru ...
随机推荐
- vector(相对线程安全) arryList(线程不安全)
1.什么是线程安全? 如果说某个集合是线程安全的,那么我们就不用考虑并发访问这个集合?(需要定义自己百度,但是很难懂) 2.深入jvm中的线程安全的级别. a不变模式(String等基本类型) b.绝 ...
- Timeout Detection & Recovery (TDR)
Timeout Detection & Recovery (TDR) NVIDIA® Nsight™ Development Platform, Visual Studio Edition 2 ...
- 扯扯淡,写个更快的memcpy
写代码有时候和笃信宗教一样,一旦信仰崩溃,是最难受的事情.早年我读过云风的一篇<VC 对 memcpy 的优化>,以及<Efficiency geek 2: copying data ...
- ORA-02041: client database did not begin a transaction
.NET中访问Oracle数据库链接:ORA-02041: client database did not begin a transaction 问题的处理. .NET中访问Oracle中带有DB_ ...
- ANT打包J2EE项目war包
1.下载并安装ant 2.安装ant步骤如下 .解压下载的zip包 .进入解压的目录,把bin目录放入系统变量PATH中. eg:E:\dev_tools\apache-ant-\bin .打开cmd ...
- 【Stage3D学习笔记续】真正的3D世界(二):显示模型
虽然我们进入真3D世界了,但是上一章的Demo仍然是显示的一个平面,尽管我们的平面在3D空间中旋转可以看出一点3D透视的效果,但是既然是真3D,就要拿出点3D的样子来! 如果要显示3D模型,我们就要告 ...
- MySQL5日期类型DATETIME和TIMESTAMP相关问题详解
MySQL5日期类型DATETIME和TIMESTAMP相关问题详解 MySQL5的日期类型有三种:DATETIME.DATE和TIMESTAMP,除了DATE用来表示一个不带时分秒的是日期,另外两个 ...
- 安卓Android控件ListView获取item中EditText值
可以明确,现在没有直接方法可以获得ListView中每一行EditText的值. 解决方案:重写BaseAdapter,然后自行获取ListView中每行输入的EditText值. 大概算法:重写Ba ...
- python爬虫之採集——360联想词W2版本号
http://blog.csdn.net/recsysml/article/details/30541197,我的这个博文介绍了对应的简单的方法做一个联想词的爬虫,并且还承诺了下面优化: 下一版本号的 ...
- SAP-SD-ABAP-VMOD 查找和应用SD模块用户出口(user exit) 好方法 .
针对 SD 模块,有一个专门管理 user-exit 的开发包 VMOD , 只要用tcode: se80 查看它, 会发现绝大部分的 SD 要相关的 user-exit 都能在这找到.