【(伪)递归】HDU1997 - 汉诺塔VII(非递归解法)

2023-12-15 22:38

本文主要是介绍【(伪)递归】HDU1997 - 汉诺塔VII(非递归解法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



汉诺塔大家应该很熟悉了吧?啥!?没听说过!?上面那么大一张图片是什么?

这次学长出了一道很DT的题(不要问我啥是DT,打开搜狗输入法输入dt按两下等号再按一下空格就知道了),看了看大神们的解……嗯……看不懂,但是中心思想还是大差不差,他们都用了递归啦、打表啦,我就想着不用递归试试!


【题目】

汉诺塔VII

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)


Problem Description
n个盘子的汉诺塔问题的最少移动次数是2^n-1,即在移动过程中会产生2^n个系列。由于发生错移产生的系列就增加了,这种错误是放错了柱子,并不会把大盘放到小盘上,即各柱子从下往上的大小仍保持如下关系 : 
n=m+p+q
a1>a2>...>am
b1>b2>...>bp
c1>c2>...>cq
ai是A柱上的盘的盘号系列,bi是B柱上的盘的盘号系列, ci是C柱上的盘的盘号系列,最初目标是将A柱上的n个盘子移到C盘. 给出1个系列,判断它是否是在正确的移动中产生的系列.
例1:n=3
3
2
1
是正确的
例2:n=3
3
1
2
是不正确的。
注:对于例2如果目标是将A柱上的n个盘子移到B盘. 则是正确的.

Input
包含多组数据,首先输入T,表示有T组数据.每组数据4行,第1行N是盘子的数目N<=64.
后3行如下
m a1 a2 ...am
p b1 b2 ...bp
q c1 c2 ...cq
N=m+p+q,0<=m<=N,0<=p<=N,0<=q<=N,

Output
对于每组数据,判断它是否是在正确的移动中产生的系列.正确输出true,否则false 

Sample Input
     
6 3 1 3 1 2 1 1 3 1 3 1 1 1 2 6 3 6 5 4 1 1 2 3 2 6 3 6 5 4 2 3 2 1 1 3 1 3 1 2 1 1 20 2 20 17 2 19 18 16 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

Sample Output
     
true false false false true true



【解题思路】


汉诺塔移动盘子的步骤(步骤自行百度)是一定的,这就会有一定的规律,规律是,最下面的盘子一定会出现在目标柱子和起始柱子上,比如有3个盘子从大到小标号为3、2、1,要把他们从A柱移到C柱上,那么3号盘子一定不可能出现在B柱上,因为移3号盘子时是直接从起始柱(此时为A柱)移到目标柱(此时为C柱上的),那么当把3移到C柱上之后,此时A柱上就没有盘子了,而B柱从下往上数是2、1号盘子,此时2号盘子便成了剩下盘子中接下来将要移至目标柱(C柱)的最大号盘子了,而对于2号盘子,此时它的起始柱为B柱,目标柱为C柱,所以在以后的步骤中,2盘是不可能出现在此时的中间柱A柱上的。

如果盘子多了,不管什么情况,最下面待移动的最大盘子的目标柱一定是C,起始柱当最大盘子编号换一次,柱子在A、B之间换一次,当然最最大的盘子的起始柱一定是A柱。

所以检测最下面最大的盘子位置是否正确时分三种情况:

1、当前最大的待移动的盘子在起始柱上(正确位置I)。

此时接着检测第二大的待移动的盘子,而这个时候第二大的待移动的盘子需要被移到对于最大的待移动的盘子来说的中间柱上,即对于第二大的盘子,它的起始柱于最大的待移动的盘子的起始柱相同,目标柱却是最大的待移动的盘子的中间柱!

2、当前最大的待移动的盘子在目标柱上(正确位置II)。

此时还是要接着检测第二大的待移动的盘子,而这个时候第二大的待移动的盘子需要被移到对于最大的待移动的盘子来说的目标柱上,所以此时,第二大的待移动的盘子不可能粗现在最大的待移动盘子的起始柱上!

3、当前最大的待移动的盘子在中间柱上(错误位置)。

当前最大的待移动的盘子此时出现在了不该出现的柱子上,这种情况最简单,直接break出去报错!

循环检查至最小的盘子,全部出现在正确位置时即可报对了,循环时的难点就在起始柱、中间柱、目标柱的转换,转换方式如果上面的3种情况看懂了就简单了。具体还得看代码。

代码中二维数组pan[x][j]中x表示A、B、C三根柱子,j表示此时从下至上每根柱子上盘子的序号,盘子序号是从小到大的升序。

o1、o2两步分别是更换起始柱目标柱的方式。


【代码】


#includeint panduan(int k,int aa,int bb,int cc,int pan[][64]);
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
int k;
scanf("%d",&k);
int a,b,c,pan[3][64]={0};
scanf("%d",&a);
for(int i=0;i0;j--)
{
flag=1;
for(int i=0;i<64;i++)
{
if(pan[p][i]==j)
{
flag=0;
goto o1;
}			
else if(pan[q][i]==j)
{
flag=0;
goto o2;
}		
}
if(flag)
break;
o1: q=bb;m=bb;bb=cc;cc=m;
continue;
o2:	m=aa;p=bb;aa=bb;bb=m;
continue;	
}
if(flag)
return 0;
else
return 1;
}



这篇关于【(伪)递归】HDU1997 - 汉诺塔VII(非递归解法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/498155

相关文章

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT

oracle11.2g递归查询(树形结构查询)

转自: 一 二 简单语法介绍 一、树型表结构:节点ID 上级ID 节点名称二、公式: select 节点ID,节点名称,levelfrom 表connect by prior 节点ID=上级节点IDstart with 上级节点ID=节点值 oracle官网解说 开发人员:SQL 递归: 在 Oracle Database 11g 第 2 版中查询层次结构数据的快速

Leetcode面试经典150题-128.最长连续序列-递归版本另解

之前写过一篇这个题的,但是可能代码比较复杂,这回来个简洁版的,这个是递归版本 可以看看之前的版本,两个版本面试用哪个都保过 解法都在代码里,不懂就留言或者私信 class Solution {/**对于之前的解法,我现在提供一共更优的解,但是这种可能会比较难懂一些(思想方面)代码其实是很简洁的,总体思想如下:不需要排序直接把所有数放入map,map的key是当前数字,value是当前数开始的

网络层 VII(IP多播、移动IP)【★★★★★★】

一、IP 多播 1. 多播的概念 多播是让源主机一次发送的单个分组可以抵达用一个组地址标识的若干目的主机,即一对多的通信。在互联网上进行的多播,称为 IP 多播(multicast , 以前曾译为组播)。 与单播相比,在一对多的通信中,多播可大大节约网络资源。假设视频服务器向 90 台主机传送同样的视频节目,单播与多播的比较如下图所示。 下图(a)是视频服务器用单播方式向 90 台主机传

【UVA】10651-Pebble Solitaire(直接递归或者记忆化)

不知道这个题UVA的数据是怎么的,用2个方法交了,第一次直接递归,第二次记忆化剪枝,时间竟然一样!? 直接郁闷了,简单的二进制表示状态和二进制运算。 14145176 10651 Pebble Solitaire Accepted C++ 0.009 2014-09-04 09:18:21 #include<cstdio>#include<algorithm>#inclu

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置

2015多校联合训练第一场Assignment(hdu5289)三种解法

题目大意:给出一个数列,问其中存在多少连续子序列,子序列的最大值-最小值< k 这题有三种解法: 1:单调队列,时间复杂度O(n) 2:RMQ+二分,时间复杂度O(nlogn) 3:RMQ+贪心,时间复杂度O(nlogn) 一:RMQ+二分 RMQ维护最大值,最小值,枚举左端点i,二分找出最远的符合的右端点j,答案就是ans += j - i+1;(手推一下就知道) 比如1 2 3

HDU 2064 汉诺塔III(水题)

题目: http://acm.hdu.edu.cn/showproblem.php?pid=2064 题目大意: 有三根杆,求把n个圆盘从左边移到右边,最少需要移动圆盘的次数。移动规则为大盘不能放在小盘上,比原始的汉诺塔题改变的地方是,只能通过中间的杆往左右两边的杆移动。 心得: 此题心得在题外,不在题内,初看此题,尼玛吓了一跳,好像很难的样子,手贱百度了一下,只注意到俩字“水题”,赶紧