zoukankan      html  css  js  c++  java
  • BZOJ 1019: [SHOI2008]汉诺塔

    传送门

    回忆一下经典的汉诺塔的递推公式:

    $f[i]=2f[i-1]+1$,然后回忆一下过程

    发现经典汉诺塔的操作也是可以有优先级的

    所以考虑可能其他优先级也同样可以递推

    具体证明可以参照经典汉诺塔

    那么设 $f[i]=kf[i-1]+b$,考虑如何求 k,b

    暴力模拟n=1,2,3的情况,求出 f[1,2,3] 后代入就可以求出 k,b 了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    int n,k,b;
    ll f[107];
    int p[7][2];//优先级
    int m,now[4][4],Top[4];//now模拟3个柱子,Top是盘子叠的数量
    void dfs(int fa,int stp)//爆搜
    {
        if(Top[3]==m||Top[2]==m) { f[m]=stp; return; }//到达结束状态就记录f
        for(int i=1;i<=6;i++)//按优先级枚举
        {
            int a=p[i][0],b=p[i][1];
            if(a==fa||(!Top[a])) continue;//如果上一步走过了或者当前柱子没有盘子就不考虑
            if(now[a][Top[a]]>now[b][Top[b]]&&Top[b]) continue;//判断另一个位置能不能放
            Top[b]++; now[b][Top[b]]=now[a][Top[a]];//模拟放盘子
            now[a][Top[a]]=0; Top[a]--;
            dfs(p[i][1],stp+1); break;//只要找一种方案
        }
    }
    int main()
    {
        n=read(); char s[10];
        for(int i=1;i<=6;i++)
            scanf("%s",s),p[i][0]=s[0]-'A'+1,p[i][1]=s[1]-'A'+1;
        for(m=1;m<=3;m++)
        {
            memset(now,0,sizeof(now));
            memset(Top,0,sizeof(Top)); Top[1]=m;
            for(int i=1;i<=m;i++) now[1][i]=m-i+1;
            dfs(0,0);
        }
        k=(f[3]-f[2])/(f[2]-f[1]); b=f[3]-f[2]*k;
        for(int i=4;i<=n;i++) f[i]=f[i-1]*k+b;
        cout<<f[n];
        return 0;
    }

     

  • 相关阅读:
    iOS中的两种主要架构及其优缺点浅析
    iOS
    iOS开发人员不容错过的10大工具
    安装CocoaPods报错
    把你唱的歌用乐器表达出来

    String.Split函数
    四部和声
    SerializeField和HideInInspector
    十年许嵩雅俗共赏
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10138476.html
Copyright © 2011-2022 走看看