首页 > 其他 > 详细

BZOJ1019 汉诺塔/洛谷P4285 [SHOI2008]汉诺塔

时间:2020-02-23 17:30:29      阅读:80      评论:0      收藏:0      [点我收藏+]

汉诺塔(BZOJ)
P4285 [SHOI2008]汉诺塔
居然是省选题,还是DP!(我的DP菜得要死,碰见就丢分)

冥思苦想了1h+ \(\to\) ?!

就是普通的hanoi NOI or HNOI? DP加上一个乱搞的数组,然后我还写反了一次,就gg了。

大概思路:

\(dp_{i,j}\)表示从柱子i移动j个盘子的最优解,\(f_{i,j}\) 表示从柱子i移动j个盘子到哪个柱子最优。然后就可以转移了!

先把i-1个盘子从x移到 \(y=f_{x,i-1}\) ,设另一根为z,然后分类:

1.\(f_{y,i-1}=y\),直接舍掉,不用DP了。

2.\(f_{y,i-1}=z\),那么把i-1个盘子从x移到y,把第i个移到z,然后把y上的i-1个移到z。
\(dp_{x,i}=dp_{x,i-1}+1+dp_{y,x-1},f_{i,j}=z\)

3.\(f_{y,i-1}=x\),把i-1个盘子先从x移到z,再把第i-1个从y移到x,再把z上的第i个移到y,再把x上i-1个的移到y
\(dp_{x,i}=dp_{x,i-1}+1+dp_{y,i-1}+1+dp_{x,i-1},f_{i,j}=y\)
最后 \(dp_{1,n}\) 就是答案

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=35;
char s[5];
int n;
int dp[N][N],f[4][N],from[7],to[7];
signed main()
{
    scanf("%lld",&n);
    for(int i=1;i<=6;++i)
    {
        scanf("%s",s);
        from[i]=s[0]-'A'+1,to[i]=s[1]-'A'+1;
    }
    for(int i=6;i>=1;--i)f[from[i]][1]=to[i];
    dp[1][1]=dp[2][1]=dp[3][1]=1;
    for(int i=2;i<=n;++i)
    {
        for(int j=1;j<=3;++j)
        {
            int x=j,y=f[x][i-1],z=6-x-y;
            if(f[y][i-1]==z)
            {
                dp[x][i]=dp[y][i-1]+1+dp[x][i-1];
                f[x][i]=z;
            }
            if(f[y][i-1]==x)
            {
                dp[x][i]=dp[y][i-1]+1+dp[x][i-1]+1+dp[x][i-1];
                f[x][i]=y;
            }
        }
    }
    printf("%lld\n",dp[1][n]);
    return 0;
}

BZOJ1019 汉诺塔/洛谷P4285 [SHOI2008]汉诺塔

原文:https://www.cnblogs.com/zzctommy/p/12350610.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!