HDU 1997(汉诺塔VII 思想很NB)

spoiler posted @ 2011年4月18日 20:44 in 规律及递归经典题 , 2280 阅读

题目大意;

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
 
题目分析:
             这个题目幸好只是判断他是不是最优化的,不然真的TBT了,我也是刚刚才能理解,网上解题报告几乎都没说什么思路,琢磨了好久~
其实
1) 最初我们要判断一下是不是已经完全放好了,这样就不用考虑是不是最优化了, 因为都已经放好了,肯定是最合法的! 或者说全部在A上,这是还没开始动作的一个状态,所以也是合法的!
2) 否则我们  要对每次状态的最大的那个进行判断,因为我们知道,汉诺塔最大的那个不可能停在B上,(假设 最初的时候都在A上,要移到C上去!),只可能在A或者C上面!如果是放在B上面,停止判断,直接断定他非法~这样我们得出了第二个判段依据!
3)如果最大的在A上面,我可以想到的是,他还没有放在C上,此时这个状态的上面一系列状态都是想把其他的放在B上,然后就可以把A放到C上了,所以我们在这里做出更新,因为他上面一系列动作都是想让A上面的除最大的外都放到B上面去,所以,我们这个时候往上考虑,对N-1进行 判断!这个时候动作的方向是A->B所以为了统一操作,我们得把B跟C互换!
4)如果最大的在C上面,这时候倒数第二大的不是放在B上就是C上,我们要把要把倒数第二大的以及其他的放在C上,这时候的动作方向是B—>C;所以把A跟B交换一下!
代码:
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
	int one[4],n[4],h[4][1000];
	int a,b,c,i,N;
	int cas,t;
	bool flag;	
	scanf("%d",&cas);
	while(cas--){
		a=1;	b=2;	c=3;
		one[a]=1,one[b]=1,one[c]=1;
		scanf("%d",&N);
		scanf("%d",&n[a]);
		for(i=one[a];i<=n[a];i++)
			scanf("%d",&h[a][i]);
		scanf("%d",&n[b]);
		for(i=one[b];i<=n[b];i++)
			scanf("%d",&h[b][i]);
		scanf("%d",&n[c]);
		for(i=one[c];i<=n[c];i++)
			scanf("%d",&h[c][i]);
		while(1){
			if(n[c]==N||n[a]==N){
				flag=true;
				break;
			}
			if(n[b]>0&&h[b][one[b]]==N){
				flag=false;
				break;
			}
			if(n[a]>0&&h[a][one[a]]==N){
				N--;
				n[a]--;
				one[a]++;
				t=b;	b=c;
				c=t;
				continue;
			}
			if(h[c][one[c]]==N&&n[c]>0){
				N--;
				n[c]--;
				one[c]++;
				t=b;	b=a;
				a=t;
				continue;
			}
		}
		if(flag)
			printf("true\n");
		else
			printf("false\n");
	}
	return 0;
}

 

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter