【UVA】10795 A Different Task-汉诺塔&递归


题解

首先锁定编号最大的盘子,若它就在目标柱子上,则不移动它是最优的。而将其移动到目标柱子后,剩下的编号更小的盘子之间的移动不会受任何影响。所以每次先将编号最大的盘子(假设为 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,...,x1号盘子必然不在 s t / e d st/ed st/ed上,所以还需要提前把 1 , 2 , . . . , x − 1 1,2,...,x-1 1,2,...,x1整体移动到 6 − s t − e d 6-st-ed 6sted上(盘子编号分别为 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,x1,6stxedx)+F(ed,x1,6stxedx)+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,x1,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,x1,6stxflx)+2x1
1 , 2 , . . . , x − 1 1,2,...,x-1 1,2,...,x1整体移动到 6 − s t x − f l x 6-st_x-fl_x 6stxflx后又整体移回 f l fl fl,根据汉诺塔问题的结论,移动步数为 2 x − 1 − 1 2^{x-1}-1 2x11


代码

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值