HDU 1997 汉诺塔VII(递归)

汉诺塔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
 
/************************************************************************/

本题为中文题,相信我不做过多解释,大家也能够理解,无非就是n个盘子的汉诺塔问题,相信之前碰到过汉诺塔问题的人都应该了解解决汉诺塔问题的递归思想,为了将第n个盘从A移到C,我们势必需要先将前n-1个盘子从A移到B,待第n个盘移动到C之后,再将前n-1个盘子从B移到C,相信这一点理解起来并不是什么大问题

而该题问的就是所给的状态是不是将n个盘子从A移到C过程中必须经历的状态

我们拿n=2来举例

2 0 0      A->B    1 1 0

1 1 0      A->C    0 1 1

0 1 1      B->C    0 0 2

以上是n=2情况过程所出现的所有状态

此题关键在于进一步熟悉每个盘子每一步要移动的选择

我们都知道,第n个盘子从A移动到C,只有两种情况,即第n个盘子要么出现在A柱,要么出现在C柱,如果出现在B柱,就是不正确的移动,直接返回false;否则,递归判断第n-1个盘子的状态。第n-1个盘子的状态与第n个盘子有关,若第n个盘子在A柱,则第n-1个盘子在A柱或B柱,在C柱就是不正确的移动,返回false;若第n个盘子在C柱,则第n-1个盘子则在B柱或C柱,在A柱就是不正确的移动,返回false,就这样一直递归到标号最小的盘子

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 65;
const int inf = 2147483647;
const int mod = 2009;
int a[N],b[N],c[N],m,p,q;
bool hanoi(int t,int n,int i,int j,int k)
{
    if(!n)
        return true;
    int v=0;
    if(i<m&&a[i]==n)
        v=1,i++;
    if(j<p&&b[j]==n)
        v=2,j++;
    if(k<q&&c[k]==n)
        v=3,k++;
    if(v==t)
        return false;
    return hanoi(6-t-v,n-1,i,j,k);
}
int main()
{
    int t,n,i;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=0;i<m;i++)
            scanf("%d",&a[i]);
        scanf("%d",&p);
        for(i=0;i<p;i++)
            scanf("%d",&b[i]);
        scanf("%d",&q);
        for(i=0;i<q;i++)
            scanf("%d",&c[i]);
        if(hanoi(2,n,0,0,0))
            puts("true");
        else
            puts("false");
    }
}

菜鸟成长记


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值