zoukankan      html  css  js  c++  java
  • 【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个放在过渡柱子上的圆盘放到目标柱子上。
    }


  • 相关阅读:
    python多线程学习一
    https学习笔记三----OpenSSL生成root CA及签发证书
    https学习笔记二----基础密码学知识和python pycrypto库的介绍使用
    HTTPS学习笔记一----HTTPS的基础理论知识
    一只小鹅的2017
    python 全局变量的import机制
    一起来学设计模式-----工厂模式的实践
    一起来学设计模式-----创建型模式之抽象工厂
    一起来学设计模式-----创建型模式之工厂方法
    一起来学设计模式-----创建型模式之简单工厂
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632308.html
Copyright © 2011-2022 走看看