【9410】双色汉诺塔

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个放在过渡柱子上的圆盘放到目标柱子上。
}


原文地址:https://www.cnblogs.com/AWCXV/p/7632308.html