Time Limit: 1000ms second
Memory Limit: 32m 问题描述:
设A、B、C是3 个塔座。开始时,在塔座A上有一叠共n个圆盘,这些圆盘自下而上, 由大到小地叠在一起。各圆盘从小到大编号为1,2,……,n,奇数号圆盘着红色,偶数号 圆盘着蓝色,如图所示。现要求将塔座A 上的这一叠圆盘移到塔座B 上,并仍按同样顺序 叠置。在移动圆盘时应遵守以下移动规则:
规则(1):每次只能移动1 个圆盘;
规则(2):任何时刻都不允许将较大的圆盘压在较小的圆盘之上;
规则(3):任何时刻都不允许将同色圆盘叠在一起;
规则(4):在满足移动规则(1)-(3)的前提下,可将圆盘移至A,B,C中任一塔座上。
试设计一个算法,用最少的移动次数将塔座A 上的n 个圆盘移到塔座B 上,并仍按同 样顺序叠置。
算法设计:
对于给定的正整数n,计算最优移动方案。
Input
输入数据。第1 行是给定的正整数n。
Output
每一行由一个正整数k 和2 个字符c1 和c2组成,表示将第k个圆盘从塔座c1移到塔座c2上。
Sample Input
3
Sample Output
1 A B 2 A C 1 B C 3 A B 1 C A 2 C B 1 A B
【题解】
双色汉诺塔和单色汉诺塔是等价的问题。就是说双色汉诺塔的答案和单色汉诺塔的答案是一样的。
我在网上看了一下。发现看不懂原理。所以我就想。记下来就好了。
只要会单色汉诺塔就好。。
这里只考虑单色的情况。讲一下最基础的汉诺塔问题。
还是把n个圆盘从a移动到b
比如n==2.
则把最上面那个小的放在c.
然后把那个大的放在b。然后把放在c的最小的放在b。
就完成了。
然后n=3的情况。
①考虑把a上的n-1个圆盘放到c上。
②然后把a上的一个大圆盘放在b上。
③然后把c上的n-1个圆盘放到b上。
完成!
这样的确很理想。
但是要怎么放呢?
你这是空中楼阁啊!!!
我们考虑①
把a上的2个圆盘放到c上。
还记的我们n==2的情况吗。
即把2个圆盘从a放到b。我们是可以实现的。
那我们完全可以把n==3的问题转换一下。
即最下面那个圆盘就当它不存在。(因为上面两个圆盘都比它小。你是可以把它当做不存在的,谁放在上
面都没关系。);
于是我们把两个圆盘从a放到c也就等价于把两个圆盘从a放到b.只是我们原本把c当做过度的柱子使用。
现在是把b当做过度的柱子使用了。
移动的初始和目标换了一下而已。
明确了①步骤可以实现之后。
然后把2个圆盘从a放到c之后。我们把A上剩余的那个最大的圆盘。从A放到B。即②
然后又是③
把n-1个圆盘从C移动到B。
还是一样的嘛!
我们还是把那个最大的圆盘当做不存在就好。
又转换成把2个圆盘从一个柱子移动到另外一个柱子上了。(还有另外一个柱子给你当过度的使用);
可以看到N=4的时候
我们需要把3个圆盘从A移动到C。然后把一个圆盘从A移动到B。再把3个圆盘从C移动到B。
还是一样。我们只要把那个最大的圆盘当做不存在。N==4的问题又转换成N==3的问题了
即从A->C->B这些过程可以转成N==3的情况来做。
可以发现这是一个递归程序;
【代码】
/* */ #include <iostream> #include <cstdio> int k, top[4][100] = { 0 }; void mov(int,char, char , char); int main() { scanf("%d", &k); for (int i = 1; i <= k; i++) //给第一个柱子上的圆盘编号。 top[1][i] = k - i + 1; top[1][0] = k;//记录第一个柱子有多少个圆盘 mov(k,'A', 'B', 'C');//把K个柱子从A移动到B,C作为过渡的柱子。 //system("pause"); return 0; } void mov(int n,char a, char b, char c) { if (n == 0) return; mov(n - 1, a, c, b);//首先要把A上的N-1个圆盘移动到过渡柱子上,这时目标柱B变成了过渡柱。 int what = a - 'A' + 1;//接下来要把源柱上的一个剩余的圆盘放到目标柱子上。(这里的目标柱不一定是B) int k = top[what][top[what][0]];//因为我们可能在进行把N-1个圆盘放到过渡柱上这个过程。 top[what][0]--;//同理源柱也不一定是A柱。 int temp = b - 'A' + 1;//然后我们获取源柱上最高的圆盘的编号 top[temp][0]++;//把它移动到目标柱上。 top[temp][top[temp][0]] = k;//对应的柱子上的圆盘数什么的要变换。 printf("%d ", k); putchar(a); printf(" "); putchar(b); printf(" "); mov(n - 1, c, b, a);//然后把N-1个放在过渡柱子上的圆盘放到目标柱子上。 }