BZOJ2144: 跳跳棋
神题一道。
考虑题目性质。首先对于一个状态,只存在四种情况,即最左/右边的点跳到中间,中间的点跳到左/右。而对于一个状态,显然第一种情况的两种分支不能同时存在,那么题目就可以理解为从$(a,b,c)$找到一条最短的路径可以使得其到达$(x,y,z)$,你完全可以把所有状态存下来随便跑个最短路算法,但是显然是无法承受的,而再研究题目可以发现如果根据一个状态的情况连边,所形成的图是一棵树,而且还是个二叉树,那么就可以利用这个性质。那么假设现在一个状态是$(x,y,z)$,设$t1=y-x,t2=z-y$。如果$t1==t2$,那么就代表这个节点是个根节点。为了简化题目,不考虑每个节点的儿子情况,只考虑他的父亲,那么这个题目就可以看作在一棵树里找两个点的LCA。那么如何求一个节点的第$k$个祖先?
根据gcd的一些奇奇怪怪的性质,可以发现如果$t1>t2$,那么不断将最左边的点移到中间,最多可以移$\frac{t1-1}{t2}$,根据这个也很容易算出移动后的状态。
剩下的就很好搞了, 倍增二分什么的都可以,我用的是二分。
//BZOJ 2144 //by Cydiater //2016.10.20 #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #include <ctime> #include <cmath> #include <iomanip> #include <cstdlib> using namespace std; #define ll long long #define up(i,j,n) for(int i=j;i<=n;i++) #define down(i,j,n) for(int i=j;i>=n;i--) const int MAXN=1e6+5; const int oo=0x3f3f3f3f; inline int read(){ char ch=getchar();int x=0,f=1; while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int dep1,dep2,ans=0; struct Node{ int x,y,z; void Sort(){if(x>y)swap(x,y);if(x>z)swap(x,z);if(y>z)swap(y,z);} }a,b; bool operator == (Node x,Node y){return x.x==y.x&&x.y==y.y&&x.z==y.z;} namespace solution{ void init(){ a.x=read();a.y=read();a.z=read(); b.x=read();b.y=read();b.z=read(); } int get(Node node){ int x=node.x,y=node.y,z=node.z; int t1=abs(y-x),t2=abs(z-y),Ans=0; while(t1!=t2&&t1*t2!=0){ if(t1<t2)swap(t1,t2); Ans+=(t1-1)/t2; int tmp=t1;t1=t2;t2=tmp%t2; } return Ans; } Node jump(Node t,int dist){ if(get(t)<dist)return (Node){oo,oo,oo}; t.Sort(); while(dist){ if(t.y-t.x>t.z-t.y){ int t1=t.y-t.x,t2=t.z-t.y; if((t1-1)/t2<dist){ dist-=(t1-1)/t2; t.y-=(t1-1)/t2*t2; t.z-=(t1-1)/t2*t2; }else{ t.y-=dist*t2; t.z-=dist*t2; dist=0; } }else{ int t1=t.y-t.x,t2=t.z-t.y; if((t2-1)/t1<dist){ dist-=(t2-1)/t1; t.x+=(t2-1)/t1*t1; t.y+=(t2-1)/t1*t1; }else{ t.x+=dist*t1; t.y+=dist*t1; dist=0; } } } return t; } void slove(){ if(a==b){puts("YES");puts("0");return;} a.Sort();b.Sort(); dep1=get(a);dep2=get(b); if(dep1<dep2){swap(a,b);swap(dep1,dep2);} ans+=dep1-dep2; a=jump(a,dep1-dep2); if(a.x==oo){puts("NO");return;} if(a==b){puts("YES");cout<<ans<<endl;return;} int leftt=1,rightt=1000000000,mid; while(leftt+1<rightt){ mid=(leftt+rightt)>>1; if(jump(a,mid)==jump(b,mid))rightt=mid; else leftt=mid; } if(jump(a,leftt)==jump(b,leftt)&&jump(a,leftt).x!=oo){ puts("YES"); printf("%d\n",ans+(leftt<<1)); } else if(jump(a,rightt)==jump(b,rightt)&&jump(a,rightt).x!=oo){ puts("YES"); printf("%d\n",ans+(rightt<<1)); } else puts("NO"); } } int main(){ //freopen("input.in","r",stdin); using namespace solution; init(); slove(); return 0; }
BZOJ2144: 跳跳棋的更多相关文章
- bzoj2144 跳跳棋 二分
[bzoj2144]跳跳棋 Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位 ...
- BZOJ2144跳跳棋——LCA+二分
题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的 游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...
- bzoj2144: 跳跳棋(二分/倍增)
思维好题! 可以发现如果中间的点要跳到两边有两种情况,两边的点要跳到中间最多只有一种情况. 我们用一个节点表示一种状态,那么两边跳到中间的状态就是当前点的父亲,中间的点跳到两边的状态就是这个点的两个儿 ...
- BZOJ2144 跳跳棋[建模+LCA]
思维题,思路比较神仙. 个人思路过程:个人只想到了只要中间棋子开始向外跳了,以后就不应该向内跳了,这样很蠢.所以应该要么先向内跳一会,要么直接开始中间的向外跳.不知道怎么处理,就卡住了. 20pts: ...
- bzoj2144 【国家集训队2011】跳跳棋
Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...
- 【bzoj2144】跳跳棋
2144: 跳跳棋 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 492 Solved: 244[Submit][Status][Discuss] ...
- [BZOJ2144]国家集训队 跳跳棋
题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...
- [BZOJ2144][国家集训队2011]跳跳棋
题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上. 每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\),\(c\)这三个位置. 我们要通 ...
- 【LCA】bzoj 2144:跳跳棋
2144: 跳跳棋 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 248 Solved: 121[Submit][Status][Discuss] ...
随机推荐
- Could not obtain information about Windows NT group/user 'xxxx\xxxx', error code 0x5
案例描述 昨晚踢球回来,接到电话说一个系统的几个比较重要作业出错,导致系统数据有些问题.让我赶紧检查看看.检查作业日志时发现,作业报如下错误(关键信息用xxx替换) The job failed. ...
- .NET应用架构设计—面向查询的领域驱动设计实践(调整传统三层架构,外加维护型的业务开关)
阅读目录: 1.背景介绍 2.在业务层中加入核心领域模型(引入DomainModel,让逻辑.数据有家可归,变成一个完整的业务对象) 3.统一协调层Application Layer(加入协调层来转换 ...
- BOOST.Asio——Tutorial
=================================版权声明================================= 版权声明:原创文章 谢绝转载 啥说的,鄙视那些无视版权随 ...
- 问题解决——MFC error RC2170: bitmap file res\XXXXXXX.png is not in 3.00 format
=================================版权声明================================= 版权声明:原创文章 谢绝转载 请通过右侧公告中的“联系邮 ...
- Mac OS X常用操作入门指南
前两天入手一个Macbook air,在装软件过程中摸索了一些基本操作,现就常用操作进行总结, 1关于触控板: 按下(不区分左右) =鼠标左键 control+按下 ...
- dom4j读取某个元素的某个属性
一.dom4j介绍 dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点, ...
- [python]获取当前年月
import time time.strftime('%Y%m',time.localtime(time.time()))#获取当前年月
- matlab里的svmtrain的输出model里,各参数的含义
Parameters: [5x1 double] %结构体变量,依次保存的是 -s -t -d -g -r等参数 nr_class: 4 %分类的个数 totalS ...
- size_t和size_type
size_t和size_type是为了独立于及其而定义的类型,因为比如在一台电脑上int为2b,而另一台电脑上是4b,这样就给程序的可移植性带来了麻烦.为了解决这个问题,在库内定义了如上类型,其实si ...
- OpenCV 之 编译和配置
“工欲善其事,必先利其器”,下面介绍在 Win7 32位系统下,用 cmake 编译 OpenCV 的过程. 1 开发环境 1.1 Win7 Windows 7 家庭普通版,Service Pac ...