hello kity
期待您的批阅,由于写解题报告时 不一定考虑的很周到,所以如果您有什么不懂的地方,请您留言,然而一天之内我肯定会看见您信息,再对代码注释详细,让您更好的阅读
分类
最新评论
最新留言
链接
RSS
计数器
223177
功能
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; } |