SHOI2008 汉诺塔
Posted charlesss
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SHOI2008 汉诺塔相关的知识,希望对你有一定的参考价值。
我真爱汉诺塔
虽说是道紫题,但仔细想想仍适用于基础版本的汉诺塔的递推思路:对于每个情况中的底盘,必须将其上方所有的盘都先挪走。
转移到这道题上,即将每个底盘上的所有盘全部按当前最高优先级操作挪走。
进一步简化,把每个底盘上的所有盘当作一个盘,按照最高优先级操作移动即可。
理论有了,接下来又是我们喜闻乐见的数学推导
这就是就是就是就是就是道数学题,跟国王游戏一样坑
用 long long定义递推数组sum【110】
只有一个盘的时候可以一步到位,sum【1】=1
有两个盘子时,就需要开始考虑优先级的问题:
因为所有盘从A柱出发,因此要先讨论从A挪到B和C的优先级
若是B优先于C,则挪动两次后底盘和上面盘将分别处于C、B柱
若从B出发,C优先于A,则可一步到位,sum【2】=3
另一种情况下,即A优于C,上面盘会被挪回到A,底盘只能被挪到B,上面盘再挪到B,总共需要sum【2】=5
回到第五行,若C优先于B,则情况刚好相反,此为两盘的挪动步骤
那么三盘呢?必须求出数组的前三个数才能递推啊
我相信聪明机智的各位都能类比上述推法自己推出三盘的步骤,这里就不写了(学校作业要写不完了),因为推导过程是完全一样的。
那么到这里,数据基础问题已经解决了再求个递推式就完美了:(方法极其水但可行)
Let‘s 回想一下当初刷openjudge上递推汉诺塔的式子,因为上面盘要挪动两次,底盘挪动一次,我们可得出递推式为 sum[i+1]=sum[i]*2+1
类比一下,在本题中,上面盘看作一个盘,要挪动的次数假设为x,底盘要挪动的次数假设为y,则递推式为sum[i+1]=sum[i]*x+y
简单手推两组sum[i+1]和sum[i](i>3)的数据(千万别推错了),代入,用sum[2]和sum[3]表示求出的x和y的值即可(多试几次总会写出对的。。)
要注意的地方就是求两盘和三盘时,必须保证推出的步骤数正确
其次最后导出的递推式会很很很长,最好用定义变量拆开表示,不然可能会崩
(就这两地方导致我暴了4次零)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 long long miaocannotsay[40]; 5 char x[4]; 6 int miaoa[3][3]; 7 int main() 8 { 9 int n; 10 cin>>n; 11 for(int i=0;i<6;i++)//读入 12 { 13 scanf("%s",x);; 14 miaoa[x[0]-‘A‘][x[1]-‘A‘]=6-i; 15 } 16 17 miaocannotsay[1]=1; 18 if(miaoa[0][1]>miaoa[0][2])//AB AC 19 { 20 if(miaoa[1][2]<miaoa[1][0])//BC<BA 21 { 22 miaocannotsay[2]=5; 23 miaocannotsay[3]=17; 24 } 25 else 26 { 27 if(miaoa[2][0]>miaoa[2][1])//CA>CB 28 { 29 miaocannotsay[2]=3; 30 miaocannotsay[3]=7; 31 } 32 else 33 { 34 miaocannotsay[2]=3; 35 miaocannotsay[3]=9; 36 } 37 } 38 } 39 else 40 { 41 if(miaoa[2][1]<miaoa[2][0])//CB<CA 42 { 43 miaocannotsay[2]=5; 44 miaocannotsay[3]=17; 45 } 46 else 47 { 48 49 if(miaoa[1][0]>miaoa[1][2])//BA>BC 50 { 51 miaocannotsay[2]=3; 52 miaocannotsay[3]=7; 53 } 54 else 55 { 56 miaocannotsay[2]=3; 57 miaocannotsay[3]=9; 58 } 59 } 60 } 61 int m=(miaocannotsay[2]*miaocannotsay[2]-miaocannotsay[1]*miaocannotsay[3])/(miaocannotsay[2]-miaocannotsay[1]); 62 int k=miaocannotsay[2]-m; 63 for(int i=4;i<=n;i++) 64 miaocannotsay[i]=miaocannotsay[i-1]*k+m; 65 cout<<miaocannotsay[n]; 66 return 0; 67 }
祝各位冬幕节快乐
以上是关于SHOI2008 汉诺塔的主要内容,如果未能解决你的问题,请参考以下文章