题目
题目背景
原《奇怪的字符串》请前往 P2543
题目描述
跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。
我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)
跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。
写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。
输入格式
第一行包含三个整数,表示当前棋子的位置a b c。(互不相同)
第二行包含三个整数,表示目标位置x y z。(互不相同)
输出格式
如果无解,输出一行NO。
如果可以到达,第一行输出YES,第二行输出最少步数。
输入输出样例
输入 #1
1 2 3 0 3 5
输出 #1
YES 2
说明/提示
20% 输入整数的绝对值均不超过10
40% 输入整数的绝对值均不超过10000
100% 绝对值不超过10^9
#include<bits/stdc++.h> using namespace std; struct oppo{ long long a[5]; long long deep; bool operator==(const oppo x) { if(a[1]==x.a[1]&&a[2]==x.a[2]&&a[3]==x.a[3]) return 1; return 0; } }a,b; long long ans; oppo find(oppo a) { long long l1,l2,x; while(1) { l1=a.a[2]-a.a[1];l2=a.a[3]-a.a[2]; if(l1>l2) { x=l1/l2; if(!(l1%l2)) x--; a.deep+=x; a.a[2]-=x*l2; a.a[3]-=x*l2; } else if(l2>l1) { x=l2/l1; if(!(l2%l1)) x--; a.deep+=x; a.a[1]+=x*l1; a.a[2]+=x*l1; } else break; } return a; } oppo up(oppo a,long long f) { long long l1,l2,x; a.deep=0; while(f) { l1=a.a[2]-a.a[1];l2=a.a[3]-a.a[2]; if(l1>l2) { x=l1/l2; if(!(l1%l2)) x--; if(x>f) x=f; a.a[2]-=x*l2; a.a[3]-=x*l2; f-=x; } else if(l2>l1) { x=l2/l1; if(!(l2%l1)) x--; if(x>f) x=f; a.a[1]+=x*l1; a.a[2]+=x*l1; f-=x; } else break; } if(f) a.a[1]=a.a[2]=a.a[3]=-1; return a; } void GG(oppo a,oppo b) { if(a.deep<b.deep) swap(a,b); ans+=a.deep-b.deep; a=up(a,a.deep-b.deep); if(a==b) return; for(long long i=1<<30;i>0;i>>=1) { oppo x=up(a,i); oppo y=up(b,i); if(!(x==y)) { ans+=2*i; a=x; b=y; } } ans+=2; return; } int main() { cin>>a.a[1]>>a.a[2]>>a.a[3]; cin>>b.a[1]>>b.a[2]>>b.a[3]; a.deep=0;b.deep=0; sort(a.a+1,a.a+4); sort(b.a+1,b.a+4); if(find(a)==find(b)) cout<<"YES"<<endl; else { cout<<"NO"<<endl; return 0; } a.deep=find(a).deep; b.deep=find(b).deep; GG(a,b); cout<<ans<<endl; return 0; }