zoukankan      html  css  js  c++  java
  • BZOJ1019 汉诺塔/洛谷P4285 [SHOI2008]汉诺塔

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

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

    就是普通的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
    ",dp[1][n]);
    	return 0;
    }
    
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    设计模式
    Java Volatile 关键字详解
    设计模式
    设计模式
    java 希尔排序
    java 插入排序
    java 选择排序
    java 枚举
    codeforces 915D Almost Acyclic Graph 拓扑排序
    TYVJ 1728 普通平衡树
  • 原文地址:https://www.cnblogs.com/zzctommy/p/12350610.html
Copyright © 2011-2022 走看看