题解
首先锁定编号最大的盘子,若它就在目标柱子上,则不移动它是最优的。而将其移动到目标柱子后,剩下的编号更小的盘子之间的移动不会受任何影响。所以每次先将编号最大的盘子(假设为xxx)移到目标柱子上。
设xxx初始位于ststst柱子上,目标柱子为ededed,将xxx从ststst移动到ededed时,1,2,...,x−11,2,...,x-11,2,...,x−1号盘子必然不在st/edst/edst/ed上,所以还需要提前把1,2,...,x−11,2,...,x-11,2,...,x−1整体移动到6−st−ed6-st-ed6−st−ed上(盘子编号分别为1,2,31,2,31,2,3)。
移动盘子的过程可逆,所以答案即为:将初始状态移动到上述局面的步数+目标状态移动到上述局面的步数+1。设函数F(p,x,fl)F(p,x,fl)F(p,x,fl)(ppp数组表示当前局面各盘子初始在的柱子编号,将1,2,...,x1,2,...,x1,2,...,x移动到目标柱子flflfl的步数)。
则ans=F(st,x−1,6−stx−edx)+F(ed,x−1,6−stx−edx)+1ans=F(st,x-1,6-st_x-ed_x)+F(ed,x-1,6-st_x-ed_x)+1ans=F(st,x−1,6−stx−edx)+F(ed,x−1,6−stx−edx)+1。
对于F(st,x,fl)F(st,x,fl)F(st,x,fl)当stx=flst_x=flstx=fl时,F(st,x,fl)=F(st,x−1,fl)F(st,x,fl)=F(st,x-1,fl)F(st,x,fl)=F(st,x−1,fl),否则F(st,x,fl)=F(st,x−1,6−stx−flx)+2x−1F(st,x,fl)=F(st,x-1,6-st_x-fl_x)+2^{x-1}F(st,x,fl)=F(st,x−1,6−stx−flx)+2x−1
将1,2,...,x−11,2,...,x-11,2,...,x−1整体移动到6−stx−flx6-st_x-fl_x6−stx−flx后又整体移回flflfl,根据汉诺塔问题的结论,移动步数为2x−1−12^{x-1}-12x−1−1。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans;
int n,st[70],ed[70];
ll F(int *p,int x,int fl)
{
if(!x) return 0;
if(p[x]==fl) return F(p,x-1,fl);
return F(p,x-1,6-p[x]-fl)+(1LL<<(x-1));
}
int main(){
int i,j;
for(j=1;;++j){
scanf("%d",&n);if(!n) break;
for(i=1;i<=n;++i) scanf("%d",&st[i]);
for(i=1;i<=n;++i) scanf("%d",&ed[i]);
for(;n && st[n]==ed[n];--n);ans=0;
if(n) ans=F(st,n-1,6-st[n]-ed[n])+F(ed,n-1,6-st[n]-ed[n])+1;
printf("Case %d: %lld\n",j,ans);
}
return 0;
}