zoukankan      html  css  js  c++  java
  • 汉诺塔【模拟】

    题目大意:

    在正常的汉诺塔规则中再加一条:不允许直接把盘从1号柱移动到3号柱,也不允许直接把盘从3号柱移动到1号柱。初始状态为第0步,编程求在某步数时的状态。


    思路:

    如果把汉诺塔的变化打出来,那么就是这样的:

    1. (1,1,1)
    2. (2,1,1)
    3. (3,1,1)
    4. (3,2,1)
    5. (2,2,1)
    6. (1,2,1)
    7. (1,3,1)
    8. (2,3,1)
    9. (3,3,1)
    10. (3,3,2)
    11. (2,3,2)
    12. (1,3,2)
    13. (1,2,2)
    14. (2,2,2)
    15. (3,2,2)
    16. (3,1,2)
    17. (2,1,2)
    18. (1,1,2)
    19. (1,1,3)
    20. (2,1,3)
    21. (3,1,3)
    22. (3,2,3)
    23. (2,2,3)
    24. (1,2,3)
    25. (1,3,3)
    26. (2,3,3)
    27. (3,3,3)

    然后,就能发现:
    1号圆盘在移动3次中,共移动了2次;2号圆盘在移动9次中,共移动了2次;3号圆盘在移动27次中,共移动了2次。
    那么也就很容易推出:n号圆盘每移动3n次中,会移动两次!
    那么这道题就很好做了,预处理3n,每次可以利用周期问题求出答案。
    时间复杂度:O(tn),最坏950000


    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const char o[]={'1','2','3','2'};
    int t,n,m,num[31],k;
    
    int main()
    {
        scanf("%d",&t);
        num[0]=1;
        for (int i=1;i<=19;i++)
         num[i]=num[i-1]*3;  //预处理
        while (t--)  //t组数据
        {
            scanf("%d%d",&n,&m);
            if (!m)   //特判,没有移动
            {
                for (int i=1;i<n;i++) {putchar('1');putchar(' ');}
                putchar('1');  //全部输出1
                putchar(10);
                continue;
            }
            for (int i=1;i<=n;i++)
            {
                k=(m/num[i]*2)+((m%num[i])/num[i-1]);  //找规律
                putchar(o[k%4]);  //周期
                if (i!=n) putchar(' ');
            } 
            putchar(10);
        }
        return 0;
    }
  • 相关阅读:
    verdi issues on license
    geci
    组合数据类型练习
    熟悉常用的Linux操作
    1.大数据概述
    c语言文法分析
    词法分析器#include<stdio.h> #include<string.h> #include<iostream.h> char prog[80],token[8]; char ch; int syn,p,m=0,n,row,sum=0; char *rwtab[6]={"begin","if","then","while","do","end"
    关于编译原理
    可变参数
    函数和指针
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998882.html
Copyright © 2011-2022 走看看