bzoj1019: [SHOI2008]汉诺塔

题目
题解
因为转移的优先顺序,所以到达每一个目标的转移过程是一定的。
考虑dp方程:
f[x][i]表示第x个柱子上有i个盘子,把他们都移动到g[x][i]这个柱子上要花得步数。
首先考虑i=1,因为操作有优先顺序,因此g[x][1]可以确定,f[x][1]都是1。
接下来考虑任意的i,那么我们需要把i-1个移动到g[x][i-1]上面去,再把剩下的一个移动到(1+2+3-x-g[x][i-1])上。
现在原来在x上的i个处在的两个柱子上,其中一个放了1个盘子,另一个放了i-1个盘子。
设g[x][i-1]=y,即i-1个盘子所在的柱子是y;1+2+3-x-g[x][i-1]=k,即一个盘所在的柱子是k。
分两种情况讨论:
(1)若g[y][i-1]=k,那么把这i-1个直接移到k上转移就完成了。
g[x][i]=k f[x][i]=f[x][i-1]+1+f[y][i-1]
(2)若g[y][i-1]=x,这种情况要麻烦一些:
把i-1个从y移动到x上,再把1个从k移动到y上,最后把i-1个从x上移动到y上。
g[x][i]=y f[x][i]=f[x][i-1]+1+f[y][i-1]+1+f[x][i-1]

这道题关键在于对于操作的优先顺序只和i=1时有关。确定了i=1,i=其他数就都可以递推出来了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,i,v[32],g[32][4],from,to,j,y,k;
ll f[32][4];
char s[3];
int main(){
	scanf("%d",&n);
	for (i=1;i<=6;i++){
		scanf("%s",s);
		from=s[0]-'A'+1;to=s[1]-'A'+1;
		if (v[from]) continue;
		v[from]=1;
		g[from][1]=to;f[from][1]=1;
	}
	for (i=2;i<=n;i++)
		for (j=1;j<=3;j++){
			y=g[j][i-1];
			k=6-j-y;
			f[j][i]=f[j][i-1]+1;
			if (g[y][i-1]==k) f[j][i]+=f[y][i-1],g[j][i]=k;
			else f[j][i]+=f[y][i-1]+1+f[j][i-1],g[j][i]=y;
		}
	printf("%lld",f[1][n]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值