题解
首先锁定编号最大的盘子,若它就在目标柱子上,则不移动它是最优的。而将其移动到目标柱子后,剩下的编号更小的盘子之间的移动不会受任何影响。所以每次先将编号最大的盘子(假设为 x x x)移到目标柱子上。
设 x x x初始位于 s t st st柱子上,目标柱子为 e d ed ed,将 x x x从 s t st st移动到 e d ed ed时, 1 , 2 , . . . , x − 1 1,2,...,x-1 1,2,...,x−1号盘子必然不在 s t / e d st/ed st/ed上,所以还需要提前把 1 , 2 , . . . , x − 1 1,2,...,x-1 1,2,...,x−1整体移动到 6 − s t − e d 6-st-ed 6−st−ed上(盘子编号分别为 1 , 2 , 3 1,2,3 1,2,3)。
移动盘子的过程可逆,所以答案即为:将初始状态移动到上述局面的步数+目标状态移动到上述局面的步数+1。设函数
F
(
p
,
x
,
f
l
)
F(p,x,fl)
F(p,x,fl)(
p
p
p数组表示当前局面各盘子初始在的柱子编号,将
1
,
2
,
.
.
.
,
x
1,2,...,x
1,2,...,x移动到目标柱子
f
l
fl
fl的步数)。
则
a
n
s
=
F
(
s
t
,
x
−
1
,
6
−
s
t
x
−
e
d
x
)
+
F
(
e
d
,
x
−
1
,
6
−
s
t
x
−
e
d
x
)
+
1
ans=F(st,x-1,6-st_x-ed_x)+F(ed,x-1,6-st_x-ed_x)+1
ans=F(st,x−1,6−stx−edx)+F(ed,x−1,6−stx−edx)+1。
对于
F
(
s
t
,
x
,
f
l
)
F(st,x,fl)
F(st,x,fl)当
s
t
x
=
f
l
st_x=fl
stx=fl时,
F
(
s
t
,
x
,
f
l
)
=
F
(
s
t
,
x
−
1
,
f
l
)
F(st,x,fl)=F(st,x-1,fl)
F(st,x,fl)=F(st,x−1,fl),否则
F
(
s
t
,
x
,
f
l
)
=
F
(
s
t
,
x
−
1
,
6
−
s
t
x
−
f
l
x
)
+
2
x
−
1
F(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
−
1
1,2,...,x-1
1,2,...,x−1整体移动到
6
−
s
t
x
−
f
l
x
6-st_x-fl_x
6−stx−flx后又整体移回
f
l
fl
fl,根据汉诺塔问题的结论,移动步数为
2
x
−
1
−
1
2^{x-1}-1
2x−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;
}