【bzoj2144】跳跳棋

Description

跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。 

写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。

Input

第一行包含三个整数,表示当前棋子的位置a b c。(互不相同)第二行包含三个整数,表示目标位置x y z。(互不相同)

Output

如果无解,输出一行NO。如果可以到达,第一行输出YES,第二行输出最少步数。

Sample Input

1 2 3
0 3 5

Sample Output

YES
2【范围】20% 输入整数的绝对值均不超过1040% 输入整数的绝对值均不超过10000100% 绝对值不超过10^9

题解

首先广搜有20分

对于一个状态

例如2 3 7

中间可以往两侧跳,即2 3 7->1 2 7 / 2 3 7->2 7 11

两侧仅有一个能往中间跳,即2 3 7->3 4 7

那么所有的状态就能表示为一棵二叉树,第一种情况为其两个儿子,第二种为其父亲

问题转换为给定树上的两个结点,求其距离

直接暴力可以得40分

可以构造这样的数据

1 2 1000000000

99999998 99999999 1000000000

这样左边要一直往中间跳上上亿次

我们发现若记前两个数差t1,后两个数差t2,不妨设t1<t2

则左边最多往中间跳(t2-1)/t1次

然后只能右边往中间跳,是一个辗转相除的过程,即在logK的时间内我们可以用这种方法得到某个结点它向上K次后的结点,或者根节点,同时还可以顺便算下深度

那么只要求始终两个状态的深度d1,d2,将较深的调整到同一深度

然后二分/倍增求与lca的深度差x

ans=2*x+abs(d1-d2)

 
 #include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio> #define inf 2000000007
#define ll long long
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int t1,t2,tmp,ans;
int a[],b[];
struct data
{
int a[];
}; data cal(int *a,int k)//得到a状态向上走k次的状态
{
data ans;
int t1=a[]-a[],t2=a[]-a[];
for(int i=;i<=;i++)ans.a[i]=a[i];
if(t1==t2)return ans;
if(t1<t2)
{
int t=min(k,(t2-)/t1);
k-=t;tmp+=t;//顺便记录深度
ans.a[]+=t*t1;ans.a[]+=t*t1;
}
else
{
int t=min(k,(t1-)/t2);
k-=t;tmp+=t;
ans.a[]-=t*t2;ans.a[]-=t*t2;
}
if(k)return cal(ans.a,k);//辗转相除
else return ans;
}
bool operator!=(data a,data b)
{
for(int i=;i<=;i++)
if(a.a[i]!=b.a[i])return ;
return ;
}
int main()
{
for(int i=;i<=;i++)a[i]=read();
for(int i=;i<=;i++)b[i]=read();
sort(a+,a+),sort(b+,b+);
data t1=cal(a,inf);int d1=tmp;tmp=;
data t2=cal(b,inf);int d2=tmp;tmp=;
//t1,t2分别为a,b的根,d1,d2为深度
if(t1!=t2){puts("NO");return ;}
if(d1>d2)
{
swap(d1,d2);
for(int i=;i<=;i++)
swap(a[i],b[i]);
}
ans=d2-d1;
t1=cal(b,ans);
for(int i=;i<=;i++)
b[i]=t1.a[i];//较深的向上调整 int l=,r=d1;
while(l<=r)//二分
{
int mid=(l+r)>>;
if(cal(a,mid)!=cal(b,mid))l=mid+;
else r=mid-;
}
printf("YES\n%d",ans+*l);
}

bzoj2144 跳跳棋 二分的更多相关文章

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

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

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

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

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

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

  4. BZOJ2144: 跳跳棋

    传送门 神题一道. 考虑题目性质.首先对于一个状态,只存在四种情况,即最左/右边的点跳到中间,中间的点跳到左/右.而对于一个状态,显然第一种情况的两种分支不能同时存在,那么题目就可以理解为从$(a,b ...

  5. BZOJ2144 跳跳棋[建模+LCA]

    思维题,思路比较神仙. 个人思路过程:个人只想到了只要中间棋子开始向外跳了,以后就不应该向内跳了,这样很蠢.所以应该要么先向内跳一会,要么直接开始中间的向外跳.不知道怎么处理,就卡住了. 20pts: ...

  6. bzoj 2144: 跳跳棋——倍增/二分

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

  7. 【bzoj2144】跳跳棋

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

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

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

  9. [BZOJ2144][国家集训队2011]跳跳棋

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

随机推荐

  1. pathForResource获取资源为nil的原因

    利用NSbundle获取 资源文件的时候,如果是自己添加的文件,获取的时候纵使返回nil的解决办法.原因是因为该文件没有添加到资源文件中,只要在添加文件的时候选择添加到 Create Folder R ...

  2. docker安装Tensorflow并使用jupyter notebook

    目前网上提供的大多数的方法都是如下: docker pull tensorflow/tensorflow docker run -it -p : tensorflow/tensorflow 但是按照步 ...

  3. MINST手写数字识别(一)—— 全连接网络

    这是一个简单快速入门教程——用Keras搭建神经网络实现手写数字识别,它大部分基于Keras的源代码示例 minst_mlp.py. 1.安装依赖库 首先,你需要安装最近版本的Python,再加上一些 ...

  4. vue2.0动画

    相对于vue1.0来说,vue2.0的动画变化还是挺大的, 在1.0中,直接在元素中加 transition ,后面跟上名字. 而在vue2.0中,需要把设置动画的元素.路由放在<transit ...

  5. python之常见的坑

    li = [1,2,3,4] # [1,3,4] # 索引值是奇数的删除 for i in range(4): if i % 2 == 1: li.pop(i) # 会报错 print(li) 面试题 ...

  6. Android 使用 adb命令 远程安装apk

    Android 使用 adb命令 远程安装apk ./adb devices 列出所有设备 ./adb connect 192.168.1.89 连接到该设备 ./adb logcat 启动logca ...

  7. TCP头校验和计算算法详解

    我就不管是按“位”(bit)取反相加,还是 按“1的补码”相加了,总之就是把需要进行校验的“字串”加(+)起来,把这相加的 结果取反当做“校验和” (Checksum), 比如,相加的结果是0101, ...

  8. ios 点餐系统

    这个程序的主要界面就是一个TabBarController.总共三个标签,第一个是所有的可点的菜,第二个是已点的菜,第三个是可以留言或者查看所有留言. 下面是第一个页面: 右上角的i按钮是添加新菜,每 ...

  9. jquery 获取tbody下的第二个tr 及多级标签

    <div id="testSlider"> <div class="esriTimeSlider ies-Slider" id="t ...

  10. ES6变量解构赋值的用法

    一.数组赋值(从数组中提取值,按照对应位置,对变量赋值) 1. 完全解构(变量与值数目相等) let arr = [1, 2, 3]; let [a,b,c] = arr; console.log(a ...