要从初始状态移动到目标状态,需要建立参考状态,然后根据移动的可逆性,只需将两个状态移动到参考状态的和加起来即可;
首先,最大编号在两个状态中位置相同,则没必要移动,移动反而不够成最优解,若最优解中需移动该盘子,那么在最优解中去掉该盘子来回移动的两部依然构成解,与最优解的性质矛盾;所以只需找最大的那个不同位置的盘子,才是必须需要移动的,记为k
假设将k从1移动到2,那么必须将前k-1个盘子移动到3,然后将它移动到2,该状态即参考状态;
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int maxn = 61;
LL mi[maxn];
int n,start[maxn],finish[maxn];
LL f(int* p,int i,int final){
if(i==0) return 0;
if(p[i]==final){
return f(p,i-1,final);
}
else {
return f(p,i-1,6-final-p[i])+mi[i-1];
}
}
int main()
{
int kase=1;
mi[0] = 1;
for(int i=1;i<=60;i++) mi[i]=mi[i-1]*2;
while(scanf("%d",&n)==1 && n){
for(int i=1;i<=n;i++)
scanf("%d",&start[i]);
for(int i=1;i<=n;i++)
scanf("%d",&finish[i]);
int k=-1;
for(int i=n;i>=1;i--){
if(start[i]!=finish[i]){
k = i; break;
}
}
if(k==-1){
printf("Case %d: 0\n",kase++); continue;
}
LL res = f(start,k-1,6-start[k]-finish[k]);
res+=f(finish,k-1,6-start[k]-finish[k])+1;
printf("Case %d: %lld\n",kase++,res);
}
return 0;
}