bzoj2144: 跳跳棋 (lca+思维)

Problem

有三个棋子在一个一条数轴上,可以使其中一枚为轴,另一枚跳过去,但跳的过程中不能越过第三枚棋子。
给定初始状态,问能否达到最终状态,如果可以最少需要几步

Solution

首先先判断可不可以。
我们可以讲初末状态都转变成不能再走的状态,显然对于每种情况这种状态只有一个。
那如果不能再继续的状态一样,说明他们肯定是可以通过变换得到的;反之,最终状态都不同,显然不能跳出来…

这样我们记录下状态、跳的步数。
类似 l c a lca lca 的操作,看跳这么多步是否可以使结果一样

Code

#include <cstdio>
#include <algorithm>
using namespace std;
#define inf 1000000000
int tmp,a[5],b[5];
struct node{int a[5];};
node calc(int *a,int k){
	node ans;
	int t1=a[2]-a[1],t2=a[3]-a[2];
	for(int i=1;i<=3;i++) ans.a[i]=a[i];
	if(t1==t2) return ans;
	if(t1<t2){
		int t=min(k,(t2-1)/t1);
		k-=t;tmp+=t;
		ans.a[2]+=t*t1;ans.a[1]+=t*t1;
	}else{
		int t=min(k,(t1-1)/t2);
		k-=t;tmp+=t;
		ans.a[2]-=t*t2;ans.a[3]-=t*t2;
	}
	if(k) return calc(ans.a,k);
	return ans;
}
bool operator !=(node a,node b){
	for(int i=1;i<=3;i++)
		if(a.a[i]!=b.a[i]) return 1;
	return 0;
}
int main(){
	for(int i=1;i<=3;i++) scanf("%d",&a[i]);
	sort(a+1,a+4);
	for(int i=1;i<=3;i++) scanf("%d",&b[i]);
	sort(b+1,b+4);
	tmp=0;node t1=calc(a,inf);int d1=tmp;
	tmp=0;node t2=calc(b,inf);int d2=tmp;
	if(t1!=t2){puts("NO");return 0;}
	if(d2<d1){
		swap(d1,d2);
		for(int i=1;i<=3;i++) swap(a[i],b[i]);
	}
	int ans=d2-d1;
	t1=calc(b,ans);
	for(int i=1;i<=3;i++) b[i]=t1.a[i];
	int l=0,r=d1,cnt=0;
	while(l<=r){
		int mid=l+r>>1;
		if(calc(a,mid)!=calc(b,mid)) l=mid+1;
		else r=mid-1,cnt=mid;
	}
	printf("YES\n%d\n",ans+2*cnt);
	return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值