• bzoj1019 / P4285 [SHOI2008]汉诺塔


    P4285 [SHOI2008]汉诺塔

    递推

    题目给出了优先级,那么走法是唯一的。

    我们用$0,1,2$代表$A,B,C$三个柱子

    设$g[i][x]$为第$x$根柱子上的$i$个盘子,经过演变后最终一定会全部转移到第$g[i][x]$根柱子上

    $f[i][x]$表示第$x$根柱子上的$i$个盘子,转移到第$g[i][x]$根柱子上所用的步数。

    现在开始递推。

    假设有$i$个盘子在第$x$个盘子上

    设$y=g[i-1][x],z=3-x-y$,表示$i-1$个盘子从$x$转移到$y$后,第$i$个盘子转移到$z$柱上

    分类讨论:

    1.当$g[i-1][y]=z$时,显然最终$i$个盘子都到$z$上

    $i-1$个盘子到$y$柱上 $-->$ 第$i$个盘子到$z$柱上 $-->$ $i-1$个盘到$z$上

    $g[i][x]=z,f[i][x]=f[i-1][x]+1+f[i-1][y]$

    2.当$g[i-1][y]=x$时

    $i-1$个盘子到$y$柱上 $-->$ 第$i$个盘子到$z$柱上 $-->$ $i-1$个盘到$x$上 $-->$ 第$i$个盘子到$y$柱上 $-->$ $i-1$个盘到$y$上$

    $g[i][x]=y,f[i][x]=f[i-1][x]+1+f[i-1][y]+1+f[i-1][x]$

    而$f[1][0/1/2],g[1][0/1/2]$可以预处理。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 int g[33][3],n;
     6 long long f[33][3];
     7 char s[7][3];
     8 int main(){
     9     scanf("%d",&n);
    10     for(int i=6;i;--i) scanf("%s",s[i]);
    11     for(int i=1;i<=6;++i)//倒着更新方便存优先级。
    12         g[1][s[i][0]-'A']=s[i][1]-'A';
    13     f[1][0]=f[1][1]=f[1][2]=1;
    14     for(int i=2;i<=n;++i)
    15         for(int x=0;x<=2;++x){
    16             int y=g[i-1][x],z=3-x-y;
    17             if(g[i-1][y]==z)
    18                 g[i][x]=z,f[i][x]=f[i-1][x]+1+f[i-1][y];
    19             else if(g[i-1][y]==x)
    20                 g[i][x]=y,f[i][x]=f[i-1][x]+1+f[i-1][y]+1+f[i-1][x];
    21         }
    22     printf("%lld",f[n][0]);
    23     return 0;
    24 }
    View Code
  • 相关阅读:
    JAVA 正则表达式 (超详细)
    <select>改造成<s:select>实现表单的回显功能
    打开新界面
    list删除操作 java.util.ConcurrentModificationException
    C# 增加 删除 更新 方法
    C# 网页内容获取
    excel 处理方法
    C# 读取excel
    sql 导入excel 遇到问题
    DataSet
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10181398.html
Copyright © 2020-2023  润新知