P1852 [国家集训队]跳跳棋
题目背景
原《奇怪的字符串》请前往 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> #define LL long long const LL INF=1e10; using namespace std; struct Q{int x,y,z;}; LL res; bool operator != (Q a,Q b){ return a.x!=b.x||a.y!=b.y||a.z!=b.z; } Q Get(Q a,LL k){ res=0; while(k){ int t1=a.y-a.x,t2=a.z-a.y; if(t1==t2) return a; if(t1<t2){ int tmp=(int)min(k,(LL)(t2-1)/t1); k-=tmp;res+=tmp; a.x+=tmp*t1;a.y+=tmp*t1; } else{ int tmp=(int)min(k,(LL)(t1-1)/t2); k-=tmp;res+=tmp; a.y-=tmp*t2;a.z-=tmp*t2; } } return a; } int a[3]; int main(){ //freopen("nt2011_hop.in","r",stdin);freopen("nt2011_hop.out","w",stdout); Q s,t;int d1,d2,ans; for(int i=0;i<3;i++) scanf("%d",&a[i]); sort(a,a+3); s=(Q){a[0],a[1],a[2]}; for(int i=0;i<3;i++) scanf("%d",&a[i]); sort(a,a+3); t=(Q){a[0],a[1],a[2]}; Q t1=Get(s,INF);d1=res; Q t2=Get(t,INF);d2=res; if(t1!=t2){puts("NO");return 0;} puts("YES"); if(d1<d2){ ans=d2-d1;t=Get(t,d2-d1); } else{ ans=d1-d2;s=Get(s,d1-d2); } LL l=0,r=INF,mid; while(l!=r){ mid=(l+r)>>1; if(Get(s,mid)!=Get(t,mid)) l=mid+1; else r=mid; } printf("%lld ",l*2+ans); return 0; }