「SHOI 2008」汉诺塔

题目大意:

由于有优先级存在,操作序列是唯一的。

设 $g[i][j]$ 表示有 $i$ 个盘在 $j$ 柱,经过一系列操作,他们都到了哪个柱子上。这是唯一确定的。我们再设这个过程的操作步数为 $f[i][j]$。

分两种情况讨论,设当前有 $i$ 个盘子在 $a$ 柱,$g[i-1][a]=b$,另一个柱子为 $c$,那么

  • 若 $g[i-1][b]=c$,说明 $g[i][a]=c$,步数为 $f[i-1][a]+1+f[i-1][b]$

  • 若 $g[i-1][b]=a$,说明 $g[i][a]=b$,步数为 $f[i-1][a]+1+f[i-1][b]+1+f[i-1][a]$

#include <cstdio>

int n, g[55][3]; long long f[55][3]; char s[10][5];

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= 6; ++i) scanf("%s", s[i]);
    for (int i = 6; i >= 1; --i) g[1][s[i][0]-'A'] = s[i][1] - 'A';
    f[1][0] = f[1][1] = f[1][2] = 1;
    for (int i = 2; i <= n; ++i)
        for (int a = 0; a < 3; ++a) { //a柱上有i个盘子
            int b = g[i-1][a], c = 3 - a - b;
            if (g[i-1][b] == c) g[i][a] = c, f[i][a] = f[i-1][a] + f[i-1][b] + 1;
            else g[i][a] = b, f[i][a] = (f[i-1][a] << 1) + f[i-1][b] + 2;
        }
    printf("%lld\n", f[n][0]);
    return 0;
}