P1852 [国家集训队]跳跳棋

二次信任 提交于 2019-11-26 16:50:16

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\n",l*2+ans);      return 0;  }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!