题目描述

跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。

我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)

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

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

输入输出格式

输入格式:

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

第二行包含三个整数,表示目标位置x y z。(互不相同)

输出格式:

如果无解,输出一行NO。

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

输入输出样例

输入样例#1: 复制

1 2 3
0 3 5
输出样例#1: 复制

YES
2

说明

20% 输入整数的绝对值均不超过10

40% 输入整数的绝对值均不超过10000

100% 绝对值不超过10^9

分析

这个题目是真的蛇皮,没话讲。

本题是一道LCA加二分的题目,以我的智商是看不出来的。

下面就来说一下我在SAC大佬的帮助下怎么分析的吧。

设最左边的棋子为a,中间棋子为b,最右边的棋子为c。

显而易见只有三种跳跃方式。

1.b往左边跳。

2.b往右边跳。

3.离b近的往里跳(离b远的不可以跳,因为会越过两个棋子)。

当a,c距离和b一样时,就把当前状态设为a,b,c的起始状态,而且a,b,c的起始状态只有一种。

所以判断一下a,b,c起始状态和不和x,y,z的起始状态一不一样就行了。

怎么判断呢?

显然,两个棋子往中间跳才可以回到起始状态。

但是,如果纯模拟的话就又会超时。

比如1,2,100000000。

这样就会进行很多次操作。

此时,设d1=b-a,d2=c-b。

d1小于d2时我们移动a,然后会发现d1没变,d2减小了d1所以我们可以连续走d2/d1次,反之亦然,此时d2小于d1了换个方向走。注意:d2%d1等于0时走d2/d1-1步就到根了。

然后怎么判断要走多少步呢?

枚举显然不行。

那就二分吧。

如果当前二分得到的mid可以使他们状态相同。

缩小上界,否则扩大下界,下面就贴上代码了(自认为写的很清楚)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
void sot(ll &a,ll &b,ll &c)
{
if(a>b)
swap(a,b);
if(a>c)
swap(a,c);
if(b>c)
swap(b,c);
}
ll min(ll x,ll y)
{
if(x>y)
return y;
return x;
}
ll getfa(ll a,ll b,ll c,ll &dep,ll &d)
{
ll d1=b-a,d2=c-b;
while(d1!=d2)
{
if(d1<d2)
{
ll sum=d2/d1,t=d2%d1;
if(t==)
{
dep+=(sum-);
d=d1;
return a+(sum-)*d1;
}
else
{
dep+=sum;
d2=t;
a+=(sum)*d1;
b+=(sum)*d1; }
}
else
{
ll sum=d1/d2,t=d1%d2;
if(t==)
{
dep+=(sum-);
d=d2;
return a;
}
else
{
dep+=sum;
d1=t;
b-=(sum)*d2;
c-=(sum)*d2;
}
}
}
dep=;
d=d1;
return a;
}
void fa(ll &a,ll &b,ll &c,ll step)
{
ll d1=b-a,d2=c-b;
while(step>)
{
if(d1<d2)
{
ll sum=d2/d1,t=d2%d1;
if(sum>=step)
{
a+=step*d1;
b+=step*d1;
if(b==c) b=a,a-=d1;
return;
}
else
{
step-=sum;
b=c-t;
a=b-d1;
d2=t;
}
}
else
{
ll sum=d1/d2,t=d1%d2;
if(sum>=step)
{
b-=step*d2;
c-=step*d2;
if(a==b) b=c,c+=d2;
return;
}
else
{
step-=sum;
b=a+t;
c=b+d2;
d1=t;
}
}
}
}
int main()
{
ll a,b,c,x,y,z,dep1=,dep2=,len=,k=,kk=;
cin>>a>>b>>c>>x>>y>>z;
sot(a,b,c);
sot(x,y,z);
ll kzj=getfa(a,b,c,dep1,k);
ll pwq=getfa(x,y,z,dep2,kk);
if(k!=kk||kzj!=pwq) {cout<<"NO";return ;}
else
{
if(dep1<dep2)
{
len+=dep2-dep1;
fa(x,y,z,len);
}
else
{
len+=dep1-dep2;
fa(a,b,c,len);
}
}
ll l=,r=min(dep1,dep2),ans=;
while(l<=r)
{
ll mid=(l+r)/;
ll a1=a,b1=b,c1=c,x1=x,y1=y,z1=z;
fa(a1,b1,c1,mid);
fa(x1,y1,z1,mid);
if(a1==x1&&b1==y1&&c1==z1)
r=mid-,ans=mid;
else
l=mid+;
}
cout<<"YES"<<endl;
cout<<ans*+len;
}

[BZOJ2144]国家集训队 跳跳棋的更多相关文章

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

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

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

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

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

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

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

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

  5. Luogu P1852 BZOJ 2144 [国家集训队]跳跳棋

    qwq 这题一看就不会,如果不是gg让做我是坚决不会做的 画图模拟,因为一次只能跳过一个棋子,所以对于一种情况只有三种移动方式: 中间向左跳 中间向右跳 左或右(距中间近的那个)向中间跳 发现,除了跳 ...

  6. luogu P1852 [国家集训队]跳跳棋

    luogu 直接操作是不可能的,考虑发现一些性质.可以发现如果每次跳的棋子都是两边的,那么最多只有一种方案,那么就把这样操作得到的状态记为当前状态的父亲,从一个状态这样做一定会结束.那么如果两个状态只 ...

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

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

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

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

  9. bzoj2144 跳跳棋 二分

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

随机推荐

  1. 算法导论 第一章and第二章(python)

    算法导论 第一章 算法     输入--(算法)-->输出   解决的问题     识别DNA(排序,最长公共子序列,) # 确定一部分用法     互联网快速访问索引     电子商务(数值算 ...

  2. Fidder详解-抓取HTTPS清求(Web/App)抓包分析(靠谱篇)

    为什么要学Fidder抓包? 学习接口,必须要学http协议,不要求您对协议的掌握有多深.只是希望你能够了解什么是协议.协议的报文.状态码等等!本文通过抓包工具Fidder带你进入接口的大门.我们通过 ...

  3. PTA 03-树1 树的同构 (25分)

    题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/711 5-3 树的同构   (25分) 给定两棵树T1和T2.如果T1可以通过若干次左右 ...

  4. JS Enter键跳转 控件获得焦点

    //回车跳转 jQuery(document).ready(function () { //$(':input:text:first').focus(); jQuery(':input:enabled ...

  5. SPOJ1812 - Longest Common Substring II(LCS2)

    Portal,Portal to 洛谷 Description 给出\(n(n\leq10)\)个仅包含小写字母的字符串\(s_1..s_n(|s_i|\leq10^5)\),求这些字符串的最长公共子 ...

  6. HDU 2352 Verdis Quo

    罗马数字转化为十进制的值 题目非常的长 提取有效信息 并且介绍很多规则 但是事实上有用的信息就是如何加 什么时候减 当当前字母小于下一个字母时 减去当前字母的值 #include <iostre ...

  7. 背包DP 整理

    题目 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 基本思路 这是最基础的背包问题,特点是: ...

  8. 【NOIP模拟】数字对(RMQ,二分)

    题意:小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n). 这个特 ...

  9. Git学习之常见错误 git push 失败

    Git学习之常见错误 git push 失败 问题描述: git push Counting objects: , done. Delta compression using up to thread ...

  10. 学习swift从青铜到王者之swift闭包06

    语法表达式 一般形式:{ (parameters) -> returnType in statements } 这里的参数(parameters),可以是in-out(输入输出参数),但不能设定 ...