Problem:

洛谷端题目链接

loj端题目链接

题目大意:

在一条数轴上进行跳跳棋游戏。棋子只能摆在整点上。每个点不能摆超过一个棋子。用跳跳棋完成:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。

跳动的规则:任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。如果可以完成输出YES以及所需步数,如果不行输出NO即可。

对,只允许跳过一颗棋子(因为这个想了好久自闭了)


Solution:

看完题目之后第一反应是不是:woc这什么,跟LCA有什么关系??这哪来的树??

那就对了(%dalao)

分类讨论,发现对于每一种合法的状态(也就是没有棋子重合)只有三种情况能走

1.中点(y)向左边跳

2.中点(y)向右边跳

3.左边(或者右边)往中间跳 =>可以证明由于只能跳过一颗棋子,在d1!=d2时只能走一个

这好像有点像二叉树?(将1.2看做子节点,3看做父亲节点)

对于1.2情况,我们可以发现(以下以1为例):

可以知道,d1>d2时左边的棋子不能跳了,我们最多走d2/d1步,此时d2小于d1了换个方向走,当d2%d1等于0时走d2/d1-1步就到根了。

所以根据这个,我们可以求出开始状态与结束状态的祖先,判断他们的祖先是否相等 =>因为祖先相同就可以通过相反操作得到

这个操作模拟一下就好了,我们可以用除来加快跳((一个个跳会超时的)

模拟部分:

                 int d1=y-x;
int d2=z-y;
if(d1<d2)
{
int step=d2/d1;
if(d2%d1==) step--;
if(step>dis) step=dis;
x+=step*d1;
y+=step*d1;
if(x>y) swap(x,y);
dis-=step;
}
else
{
int step=d1/d2;
if(d1%d2==) step--;
if(step>dis) step=dis;
z-=d2*step;
y-=d2*step;
if(z<y) swap(z,y);
dis-=step;
}

找到了公共祖先之后就可以二分查找(查找往上跳的步数) 

l是0,r是min(结果与公共祖先的距离,起点与公共祖先的距离)

                 int l=,r=min(dep1,dep2),step=;
while(l<=r)
{
int mid=l+r>>;
b1=go(st,mid);
b2=go(ed,mid);
if(pd(b1,b2)) step=mid,r=mid-;
else l=mid+;
}

以上是我认为的核心内容(看不懂就感性理解一下)


#include<iostream>
#include<cstdio>
using namespace std;
struct node{
int x,y,z;
}st,ed,b1,b2;
int dep1,dep2;
inline int read(){
char ch;
int sign=;
while((ch=getchar())<''||ch>'')
if(ch=='-') sign=-;
int res=ch-'';
while((ch=getchar())>=''&&ch<='')
res=res*+ch-'';
return res*sign;
}
inline void sort(node &x){
if(x.x>x.y) swap(x.x,x.y);
if(x.x>x.z) swap(x.x,x.z);
if(x.y>x.z) swap(x.y,x.z);
}
inline int findfather(node &b){
int res=;
sort(b);
while(b.x+b.z!=b.y*){
int d1=b.y-b.x;
int d2=b.z-b.y;
if(d1<d2){
int step=d2/d1;
if(d2%d1==) step--;
b.x+=step*d1;
b.y+=step*d1;
if(b.x>b.y) swap(b.x,b.y);
res+=step;
}else{
int step=d1/d2;
if(d1%d2==) step--;
b.z-=step*d2;
b.y-=step*d2;
if(b.y>b.z) swap(b.y,b.z);
res+=step;
}
}
return res;
}
inline bool pd(node x,node y){
if(x.x==y.x&&x.y==y.y&&x.z==y.z) return true;
return false;
}
inline int abs(int x){
return x>=?x:-x;
}
inline node go(node b,int dis){
sort(b);
while(dis){
int d1=b.y-b.x;
int d2=b.z-b.y;
if(d1<d2){
int step=d2/d1;
if(d2%d1==) step--;
if(step>dis) step=dis;
b.x+=step*d1;
b.y+=step*d1;
if(b.x>b.y) swap(b.x,b.y);
dis-=step;
}else{
int step=d1/d2;
if(d1%d2==) step--;
if(step>dis) step=dis;
b.z-=d2*step;
b.y-=d2*step;
if(b.z<b.y) swap(b.z,b.y);
dis-=step;
}
}
return b;
}
int main(){
st.x=read();st.y=read();st.z=read();
ed.x=read();ed.y=read();ed.z=read();
sort(st);sort(ed);
b1=st;b2=ed;
dep1=findfather(b1);
dep2=findfather(b2);
if(!pd(b1,b2)){
printf("NO\n");
return ;
}else{
int c=abs(dep1-dep2);
if(dep1<dep2)
ed=go(ed,c);
else if(dep1>dep2)
st=go(st,c);
int l=,r=min(dep1,dep2),step=;
while(l<=r){
int mid=l+r>>;
b1=go(st,mid);
b2=go(ed,mid);
if(pd(b1,b2)) step=mid,r=mid-;
else l=mid+;
}
printf("YES\n");
printf("%d",step*+c);
}
return ;
}

complete code

不一样的LCA——luoguP1852跳跳棋的更多相关文章

  1. 【LCA】bzoj 2144:跳跳棋

    2144: 跳跳棋 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 248  Solved: 121[Submit][Status][Discuss] ...

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

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

  3. 【洛谷】1852:[国家集训队]跳跳棋【LCA】【倍增?】

    P1852 [国家集训队]跳跳棋 题目背景 原<奇怪的字符串>请前往 P2543 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个 ...

  4. 【BZOJ 2144】 2144: 跳跳棋 (倍增LCA)

    2144: 跳跳棋 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 642  Solved: 307 Description 跳跳棋是在一条数轴上进行的 ...

  5. 跳跳棋——二分+建模LCA

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

  6. P1852 跳跳棋 [LCA思想+二分答案]

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

  7. bzoj2144 【国家集训队2011】跳跳棋

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

  8. 跳跳棋(9018_1563)(BZOJ_2144)

    题目: Hzwer的跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 某一天,黄金大神和cjy用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.他们要 ...

  9. [BZOJ 2144]跳跳棋

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

随机推荐

  1. OKHttp和NumberProgressbar组建强大的Android版本更新功能

    你们看过韩国电影<奇怪的她>不?女主角是不是超级漂亮的.......好啦,扯正事吧,先看看女神照片. 公司新项目用到了OKHttp网络框架,在下载文件这块都蒙圈啦,再查查资料就一个Reso ...

  2. 七、Docker启动tocmat 8

    七.Docker启动tocmat 8 tomcat官方镜像中tomcat:7 和tomcat:8的目录. CATALINA_BASE: /usr/local/tomcat CATALINA_HOME: ...

  3. Odoo field字段标签属性详解

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826356.html 标签属性 1) name:标识字段名称 2)string:标签文本,如果我们想要覆盖 ...

  4. IntelliJ idea SpringBoot打war包

    简单易用的使用idea 将SpringBoot工程打war包的方法 pom.xml中添加标签 1. 声明打包格式 <packaging>war</packaging> 2.  ...

  5. nginx 安装第三方模块(lua)并热升级

    需求: nginx上将特定请求拒绝,并返回特定值. 解决办法: 使用lua脚本,实现效果. 操作步骤: 安装Luajit环境 重新编译nginx(目标机器上nginx -V 配置一致,并新增两个模块n ...

  6. nginx日志设置

    环境:nginx1.16.1 (1)日志类型:access_log(访问日志) error_log(错误日志)rewrite_log 访问日志:通过访问日志我们可以得到用户的IP地址.浏览器的信息,请 ...

  7. tomcat启动后,跳转到项目指定页面

  8. PDB files out of the debugger

    我想我不需要强调在调试时拥有有效的PDB文件有多重要.通常,PDB文件是由调试器静默加载的,并且您很高兴在modules窗口中看到解析的所有符号.不幸的是,您还可能遇到调试器找不到匹配符号的情况.其原 ...

  9. Vim Python3环境打造

    Vim Python3环境打造 tags: Vim Python3 参考网址:Vim与Python真乃天作之合:打造强大的Python开发环境 分割布局 sv 纵向分割 vs 横向分割 ctrl+W ...

  10. OI蒟蒻收集的各种网址集合(无标记

    本地收藏夹伤不起…… https://zh.wikipedia.org/wiki/Template:%E7%AE%97%E6%B3%95 https://courses.csail.mit.edu/6 ...