求三个人从a,b,c这三个位置跳到x,y,z最少多少步。跳:任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。 

从它跳的性质出发,向内跳只有一种操作,而向外跳有两种。这就是说,每个状态可以找到一个唯一前趋,有两个后继。这是一棵二叉树!求两个状态的最短路就是求他们到lca的距离和!

类似于lca,先看两个状态能跳到的最终状态是否相同,在这个过程中记下两个状态的深度。然后让深度大的先跳,跳到两个状态深度一样后,二分答案让两个一起跳。

问题是怎么快速地跳指定步数,记中间那个人和左右的间距为l和r,如果l小,那左边人往里跳一步,就会:l->l,r->r-l,更相减损,最后变成l,r%l,这r/l步可以很快跳。所以把r/l和指定步数x取个min让间隔小的那边的人跳就好了。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<algorithm>
  5 //#include<iostream>
  6 using namespace std;
  7
  8 int a,b,c,x,y,z;
  9 int ra,rb,rc,rx,ry,rz;
 10 void play(int a,int b,int c,int &ra,int &rb,int &rc,int &dep)
 11 {
 12 //  cout<<a<<' '<<b<<' '<<c<<endl;
 13     int l=b-a,r=c-b;
 14     if (l==r) {ra=a;rb=b;rc=c;return;}
 15     if (l<r)
 16     {
 17         if (!(r%l)) play(c-l-l,c-l,c,ra,rb,rc,dep),dep+=r/l-1;
 18         else play(c-r%l-l,c-r%l,c,ra,rb,rc,dep),dep+=r/l;
 19     }
 20     else
 21     {
 22         if (!(l%r)) play(a,a+r,a+r+r,ra,rb,rc,dep),dep+=l/r-1;
 23         else play(a,a+l%r,a+l%r+r,ra,rb,rc,dep),dep+=l/r;
 24     }
 25 }
 26 int ccc(int a,int b,int c)
 27 {
 28     int l=b-a,r=c-b;
 29     if (l<r)
 30     {
 31         if (!(r%l)) return r/l-1;
 32         else return r/l;
 33     }
 34     else
 35     {
 36         if (!(l%r)) return l/r-1;
 37         else return l/r;
 38     }
 39 }
 40 void jump(int &a,int &b,int &c,int x)
 41 {
 42     if (a==b || b==c) return;
 43     int l=b-a,r=c-b;
 44     if (l<r)
 45     {
 46         a+=x*l;
 47         b+=x*l;
 48     }
 49     else
 50     {
 51         c-=x*r;
 52         b-=x*r;
 53     }
 54 }
 55 //LL mul(LL a,LL b) {return a*b-(LL)((double)a/p*b)*p;}
 56 void Jump(int &a,int &b,int &c,int x)
 57 {
 58     for (;x;)
 59     {
 60         int tmp=min(x,ccc(a,b,c));
 61         jump(a,b,c,tmp);
 62         x-=tmp;
 63     }
 64 }
 65 bool check(int num)
 66 {
 67     int ta=a,tb=b,tc=c,tx=x,ty=y,tz=z;
 68 //  cout<<ta<<' '<<tb<<' '<<tc<<' '<<tx<<' '<<ty<<' '<<tz<<endl;
 69     Jump(ta,tb,tc,num);Jump(tx,ty,tz,num);//cout<<"->\n";
 70 //  cout<<ta<<' '<<tb<<' '<<tc<<' '<<tx<<' '<<ty<<' '<<tz<<endl;
 71     return ta==tx && tb==ty && tc==tz;
 72 }
 73 void sos(int &a,int &b,int &c)
 74 {
 75     if (a>b) {int t=a;a=b;b=t;}
 76     if (a>c) {int t=a;a=c;c=t;}
 77     if (b>c) {int t=b;b=c;c=t;}
 78 }
 79 int main()
 80 {
 81     scanf("%d%d%d%d%d%d",&a,&b,&c,&x,&y,&z);
 82     sos(a,b,c);sos(x,y,z);
 83     int dep=0,ddd=0;
 84     play(a,b,c,ra,rb,rc,dep);play(x,y,z,rx,ry,rz,ddd);
 85 //  cout<<ra<<' '<<rb<<' '<<rc<<endl;
 86 //  cout<<rx<<' '<<ry<<' '<<rz<<endl;
 87 //  cout<<dep<<' '<<ddd<<endl;
 88     if (ra!=rx || rb!=ry || rc!=rz) puts("NO");
 89     else
 90     {
 91         puts("YES");
 92         if (dep<ddd) {swap(a,x);swap(b,y);swap(c,z);swap(dep,ddd);}
 93         int ans=0;
 94 //      cout<<a<<' '<<b<<' '<<c<<' '<<x<<' '<<y<<' '<<z<<endl;
 95         while (dep>ddd) {int tmp=min(dep-ddd,ccc(a,b,c));ans+=tmp;jump(a,b,c,tmp);dep-=tmp;}
 96 //      cout<<a<<' '<<b<<' '<<c<<' '<<x<<' '<<y<<' '<<z<<' '<<ans<<endl;}
 97         int L=0,R=ddd;
 98         while (L<R)
 99         {
100             const int mid=(L+R)>>1;
101             if (check(mid)) R=mid;
102             else L=mid+1;
103         }
104         printf("%d\n",ans+L*2);
105     }
106     return 0;
107 }
108 

View Code

转载于:https://www.cnblogs.com/Blue233333/p/7643824.html

BZOJ2144: 跳跳棋相关推荐

  1. [BZOJ2144]跳跳棋

    [BZOJ2144]跳跳棋 试题描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过 ...

  2. bzoj2144 跳跳棋

    Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...

  3. bzoj-2144 跳跳棋

    2144: 跳跳棋 题目链接 时间限制: 10 Sec 内存限制: 259 MB 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一 个简单的游戏: ...

  4. [bzoj2144]: 跳跳棋

    2144: 跳跳棋 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 689  Solved: 326 [Submit][Status][Discuss ...

  5. BZOJ2144跳跳棋——LCA+二分

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的 游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...

  6. bzoj2144: 跳跳棋(二分/倍增)

    思维好题! 可以发现如果中间的点要跳到两边有两种情况,两边的点要跳到中间最多只有一种情况. 我们用一个节点表示一种状态,那么两边跳到中间的状态就是当前点的父亲,中间的点跳到两边的状态就是这个点的两个儿 ...

  7. 洛谷1852 BZOJ2144 跳跳棋 思维题

    题目链接 题意: 坐标轴上告诉你三个互不相同的位置作为三个棋子的起点,再告诉你三个不同的位置作为三个棋子的终点,每次操作可以让一个棋子以另一个棋子为轴跳到对称位置,并且只能跳过一个棋子,问你是否能最终 ...

  8. [BZOJ2144]国家集训队 跳跳棋

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...

  9. 【BZOJ2144】跳跳棋

    [题目 描述] 跳跳棋是在一条数轴上进行的. 棋子只能摆在整点上. 每个点不能摆超过一 个棋子. 我们用跳跳棋来做一个简单的游戏: 棋盘上有 3 颗棋子, 分别在 a, b, c 这三个位置. 我们要 ...

最新文章

  1. CentOS 6.5安装nagios
  2. java_IO_File(3)_遍历、递归
  3. OpenGL之gluPerspective浅析
  4. PHP 函数截图 哈哈哈
  5. IQ不平衡补偿 Lowdin算法
  6. Windows中使用http-server搭建一个本地服务
  7. nmos导通流向_MOS管知识详细说明!结构,原理,技术参数详解,一定要进来看下...
  8. ESP定律脱压缩壳aspack
  9. 服务器cpu e系列和x系列,英特尔至强cpu,x系列和e系列哪个更好?
  10. shineblink LD3320A语音识别
  11. 计算机音乐谱大全eiei,彼岸吉他谱频道-求谱eiei,偶像练习生,求吉他谱,尤克里里谱,简谱,五线谱,钢琴谱,乐队总谱,乐谱-彼岸吉他 - 一站式吉他爱好者服务平台...
  12. Android Google原生语音识别
  13. 跨平台AR增强现实开发(一)(AR开发环境的搭建)
  14. 言语理解-片段阅读的结构剖析练习
  15. windows域控制器损坏修复过程
  16. underscore入门使用说明
  17. matlab 固态 机械_固态硬盘需要“磁盘碎片整理”吗?
  18. 干洗店收银系统应具备的功能
  19. android space控件 变成线条,学Android Space控件,只看这篇文章就行了
  20. 计算机视觉学习(六):标定手机相机参数

热门文章

  1. 三极管原理及贴片封装注意
  2. 阿里图标库彩色图标使用
  3. 如何利用 Python 批量合并 Excel?
  4. Java多用户商城源码/单商户商城系统源码
  5. 基于Java实现的商品推荐系统
  6. 复赛后第一次正经写博客
  7. 如何解决ping不通问题
  8. Python:实现fuzzy operations模糊运算算法(附完整源码)
  9. 恺撒密码算法 Java实现
  10. pinned memory or page locked memory)