link

题意

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

跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。

判断是否可以完成任务。如果可以,输出最少需要的跳动次数。

思路

神仙题……非常巧妙地建模。只能说:女少口阿

首先,对于中轴棋子为 \(b\) (中间那个)的情况,显然一直往中间跳可以一直减小范围,直到不能跳为止。这时候就得到了一个非常有用的“Basic” 状态,也就是“根状态”(这怎么跟某道字符串手玩题这么像啊)

然后把 \(b\) 往左右跳的情况看成左右节点状态,那么所有状态构成了一棵二叉树。对于棋盘上所有的 \(a,b,c\) ,状态构成了一个森林。

那么,如果 \((a,b,c)\to (x,y,z)\) ,首要条件是在同一棵树上。这样第一问就解决了。

考虑状态怎么去树根。利用 LCA 的思想,把两个状态到根的距离调整到一样,然后二分向上的步数,最后找到一个 \(L\) 使得两个状态向上 \(L\) 步相遇,那么总答案就是 高度差加上二分答案的两倍。

代码

#include <bits/stdc++.h>
using namespace std;
const int inf=1e9+7;
int sx,sy,sz,dep,mx; void init( int &x,int &y,int &z )
{
x+=inf; y+=inf; z+=inf;
if ( y>z ) swap( y,z );
if ( x>y ) swap( x,y );
if ( y>z ) swap( y,z );
} void dfs( int x,int y,int z,int step )
{
int del1=y-x,del2=z-y;
if ( step==mx || del1==del2 ) { sx=x,sy=y,sz=z; dep=step; return; }
if ( del1>del2 )
{
swap( del1,del2 ); int del=del2/del1;
if ( del2%del1==0 ) del--;
if ( step+del<=mx ) dfs( x,y-del*del1,z-del*del1,step+del );
else dfs( x,y-(mx-step)*del1,z-(mx-step)*del1,mx );
}
else
{
int del=del2/del1; del-=(del2%del1==0);
if ( step+del<=mx ) dfs( x+del*del1,y+del*del1,z,step+del );
else dfs( x+(mx-step)*del1,y+(mx-step)*del1,z,mx );
}
} int main()
{
int x,y,z,a,b,c;
scanf( "%d%d%d",&a,&b,&c ); init( a,b,c );
scanf( "%d%d%d",&x,&y,&z ); init( x,y,z ); mx=inf;
dfs( a,b,c,0 ); int sa=sx,sb=sy,sc=sz,sd=dep;
dfs( x,y,z,0 );
if ( sx!=sa || sy!=sb || sz!=sc ) { printf( "NO" ); return 0; }
printf( "YES\n" );
//------------query1-------------------
int ans=0;
if ( sd>dep )
{
ans=sd-dep; mx=sd-dep;
dfs( a,b,c,0 ); a=sx; b=sy; c=sz;
}
if ( sd<dep )
{
ans=dep-sd; mx=dep-sd;
dfs( x,y,z,0 ); x=sx,y=sy,z=sz;
} int l=0,r=inf;
while ( l<=r )
{
mx=(l+r)>>1;
dfs( a,b,c,0 ); sa=sx,sb=sy,sc=sz;
dfs( x,y,z,0 );
if ( sa!=sx || sb!=sy || sc!=sz ) l=mx+1;
else r=mx-1;
} printf( "%d",(l<<1)+ans );
}

【题解】P1852 跳跳棋的更多相关文章

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

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

  2. [luogu]P1852跳跳棋

    题目重点是每次不能跳过两个棋子 即对于每一个棋子的状态(a,b,c) (a<b<c) 最多有两种移动的方式 1.中间往两边跳 (a,b,c)-->(2b-a,a,c)或(a,c,2b ...

  3. P1852 [国家集训队]跳跳棋

    P1852 [国家集训队]跳跳棋 lca+二分 详细解析见题解 对于每组跳棋,我们可以用一个三元组(x,y,z)表示 我们发现,这个三元组的转移具有唯一性,收束性 也就是说,把每个三元组当成点,以转移 ...

  4. 洛谷 P1852 [国家集训队]跳跳棋 解题报告

    P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...

  5. 洛谷 P1852 [国家集训队] 跳跳棋

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

  6. [BZOJ 2144]跳跳棋

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

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

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

  8. 【bzoj2144】跳跳棋

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

  9. bzoj2144 跳跳棋 二分

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

随机推荐

  1. 自适应哈希索引(Adaptive Hash Index, AHI) 转

    Adaptive Hash Index, AHI 场景 比如我们每次从辅助索引查询到对应记录的主键,然后还要用主键作为search key去搜索主键B+tree才能找到记录. 当这种搜索变多了,inn ...

  2. linux命令查看日志

    首先介绍几个日志查看种常用的简单命令: 1.tail tail 命令可用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件. tail -f filename 会把 filenam ...

  3. 支持jewel版本的calamari

    之前测试了下,发现calamari不支持jewel版本的,是因为接口了有了一些变化,在提出这个问题后,作者给出了回答,说肯定会支持的,并且做了一点小的改动,就可以支持了,这个作者merge了到了git ...

  4. linux利用screen进行shell下的屏幕协作

    我们都知道linux是支持多终端并行处理的 但是某些时候我们可能有比较特殊的需求需要两个人同时处理一个终端,screen 正好能满足这个要求 首先需要安装screen软件: debian和ubuntu ...

  5. python程序基础

    高级程序设计语言包括Python.C/C++.Java等 低级程序设计语言包括汇编语言和机器语言   Python是一种解释型语言,但为了提高运行效率,Python程序在 执行一次之后会自动生成扩展名 ...

  6. Android ALSPS驱动分析

    一.alsps的初始化函数和重要结构体 epl2182_init // Epl2182.c (kernel-3.10\drivers\misc\mediatek\alsps\epl2182-new) ...

  7. img元素的联用

    img元素的常用属性: src属性:资源地址 alt属性:当图片资源失效时,将出现该属性的设置的文字 最简单的联动: 和a元素联用(直接用a标签套) <a href="https:// ...

  8. 【P2634】聪聪可可——点分治

    (题面来自Luogu) 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问题,一般情况下石头 ...

  9. [教程] Android Native内存泄漏检测方法

    转载请注明出处:https://www.cnblogs.com/zzcperf/p/9563389.html Android 检测 C/C++内存泄漏的方法越来越简便了,下面列举一下不同场景下检测C/ ...

  10. C++/Java小白解Leetcode题,发现了知识盲区……

    一.初见LeetCode 大一时候学习C++,根据课程一直在PTA平台做题目,数据结构和算法的作业题目也是在PTA.后来发现牛客网学习资源也很丰富,孤陋寡闻,前几个月在知道LeetCode这个平台,跟 ...