汉诺塔,不过规定了操作的优先级,即唯一确定了你的操作序列。
我们用f[x][i]表示把x柱子上的i个盘子移动到另一个柱子(这应该是唯一的,我们记作g[x][i])所需的步数。
然后考虑f[x][i],先把上面的i-1个挪到g[x][i-1],记作y,然后把i挪到z,这时候有两种情况:
1、g[y][i-1]==z 那么直接挪到z就好了,g[x][i]=z,f[x][i]=f[x][i-1]+1+f[y][i-1]
2、g[y][i-1]==x 那么i-1个挪回x,i挪到y,此时i-1个一定会挪到y上,因此g[x][i]=y,f[x][i]=f[x][i-1]+1+f[y][i-1]+1+f[x][i-1]
复杂度O(n)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 50
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*10+ch-'0',ch=getchar();
return x*f;
}
int n,g[3][N];//g[x][i],把x柱子上的i个盘都挪走会到的柱子
ll f[3][N];char s[N];//f[x][i],需要的步数
int main(){
// freopen("a.in","r",stdin);
n=read();memset(g,-1,sizeof(g));
for(int i=1;i<=6;++i){
scanf("%s",s+1);int x=s[1]-'A',y=s[2]-'A';
if(g[x][1]==-1) g[x][1]=y;
}for(int i=0;i<3;++i) f[i][1]=1;
for(int i=2;i<=n;++i){
for(int x=0;x<3;++x){
int y=g[x][i-1],z=3-x-y;
if(g[y][i-1]==z) g[x][i]=z,f[x][i]=f[x][i-1]+1+f[y][i-1];
else g[x][i]=y,f[x][i]=f[x][i-1]+1+f[y][i-1]+1+f[x][i-1];
}
}printf("%lld\n",f[0][n]);
return 0;
}