• BZOJ 1019: [SHOI2008]汉诺塔


    Description

    一个汉诺塔,给出了移动的优先顺序,问从A移到按照规则移到另一个柱子上的最少步数.

    规则:小的在大的上面,每次不能移动上一次移动的,选择可行的优先级最高的.

    Sol

    DP.

    倒着DP.但是他有优先级,所以他的方案是唯一的.

    状态 (f[a][i]) 表示 将 (a) 柱上的 (i) 个移到,能移动到的柱子上的步数.

    他能移动到的柱子也是唯一的,这个可以跟DP一起递推出来.

    (g[a][j]) 表示 将 (a) 柱上的 (i) 个能移动到的柱子.

    然后就开始递推了,跟普通汉诺塔一样,把 (i-1) 个先移走,然后移动第 (i) 个盘子,显然他只能移动到 (i-1) 移动到的另一个柱子,然后考虑把 (i-1) 个一回来,这时候就有问题了.. (i-1) 个在优先级的影响下可能会回到原位置,这时候就不能把这些一共 (i) 个盘子移到 (i) 所在的柱子了,所以只能将 (i) 移到 (i-1) 一开始移动到的那个柱子.

    结果就是 (f[1][n]) .

    时间复杂度 (O(n)) 

    Code

    /**************************************************************
        Problem: 1019
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:0 ms
        Memory:1288 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<iostream>
    using namespace std;
     
    #define debug(a) cout<<#a<<"="<<a<<" "
    const int N = 35;
     
    int n,b[3];
    int g[3][N];
    long long f[3][N];
     
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=6;i++){
            char fr=getchar();while(fr>'Z' || fr<'A') fr=getchar();
            char to=getchar();while(to>'Z' || to<'A') to=getchar();
            if(!b[fr-'A']) b[fr-'A']=1,g[fr-'A'][1]=to-'A',f[fr-'A'][1]=1;
        }
        for(int i=2;i<=n;i++){
            for(int a=0,b,c;a<3;a++){
                b=g[a][i-1],c=3-a-b;
                if(g[b][i-1] == c) f[a][i]=f[a][i-1]+1+f[b][i-1],g[a][i]=c;
                if(g[b][i-1] == a) f[a][i]=f[a][i-1]+1+f[b][i-1]+1+f[a][i-1],g[a][i]=b;
            }
        }cout<<f[0][n]<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    C#学习笔记:多态与隐藏,覆盖
    HTML与XML数据的结合小总结
    基于角色(RoleBased)的表单验证
    去除C++String的首尾空格
    Bash Shell中命令行选项/参数处理
    linux shell 执行多个命令的几种方法
    gdb 多线程调试
    linux 时间戳及时间差计算
    oracle sql日期比较
    在Fedora 14上安装Sun JDK 6
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6044890.html
Copyright © 2020-2023  润新知