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] ...
随机推荐
- 一个语句创建Oracle所有表的序列
-- 动态创建序列 declare cursor c_job is select TABLE_NAME from user_tables; c_row c_job%rowtype; v_sql ); ...
- Loadrunner代理录制设置
使用LR代理录制原理 启用LR代理服务器监听设置好的端口号是否有请求信息发送给服务器,有请求时,代理服务器接收带请求,并转发给对应的系统服务器,LR从而获取到请求的信息与数据,生成脚本. 使用代理的前 ...
- class.c 添加中文注释(2)
/* Class Device Stuff */ int class_device_create_file(struct class_device * class_dev, const struct ...
- Eclipse 安装 jBPM 插件
下载jbpm-installer安装包并解压,找到 jbpm-installer\build.properties搜索eclipse.home 修改 eclipse.home=./eclipse 成 ...
- Mysql日志解析
修改Mysql配置 Mysql配置地址为: C:\Program Files (x86)\MySQL\MySQL Server 5.5 如果无法修改可以把my.ini拷贝出来,修改完后,再拷贝回去! ...
- monkey之monkey简介
1.Monkey 是什么 Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序 ...
- 疑似easyui本身bug:easyui时间控件问题,试了几个版本都不行
最近发现easyui时间控件的值格式不支持带斜杠的日期(2016/10/31),必须是2016-10-31这类的才能正常使用,否则默认初始化为当前时间 <input id="Retur ...
- WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
http://dl.bintray.com/sequenceiq/sequenceiq-bin/ http://www.secdoctor.com/html/yyjs/31101.html
- image的加载事件(onload)和加载状态(complete)
之前做过这样一个需求,要让商家页的商家图片按照图片外面box的大小等比例缩放.之前的想法是在页面中先输出图片的src,然后在页面底部初始化js,然后在js中写相应的可以使图片按照box的大小等比例缩放 ...
- 深入理解Java:内部类
什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public ...