[BZOJ 2144]跳跳棋
Description
跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。 写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。
Input
第一行包含三个整数,表示当前棋子的位置a b c。(互不相同)第二行包含三个整数,表示目标位置x y z。(互不相同)
Output
如果无解,输出一行NO。如果可以到达,第一行输出YES,第二行输出最少步数。
Sample Input
0 3 5
Sample Output
2
HINT
【范围】
100% 绝对值不超过10^9
题解
设初始状态为$sta$,目标状态为$fin$。我们先拿出初始状态三个球讨论。
由于三个球其实是相同的,则他们的相互顺序是不影响的,我们可以先按坐标从左至右排序为$a$,$b$,$c$。
平面上有三个球,我们来讨论它们跳的不同情况。
设:$p=b-a$,$q=c-b$
那么$b$可以跳动到$a$左边,或者$c$右边。
同时,如果$p<q$,那么$a$可以跳到$bc$中间,如果$p>q$,那么$c$可以跳到$ab$中间。
也就是说,如果$p≠q$,那么一个状态有$3$种跳法,但如果$p=q$,那么只有$2$种跳法。
如果我们用图来表示状态之间的关系,就很容易发现,状态之间组成的联系实际上是二叉树组成的森林。
每一个$p=q$的状态都是一棵二叉树的根。
其余的每个状态,$a$或$c$往中间跳表示往父亲节点走一步,对于所有状态,中间节点往左右跳分别对应往左右孩子走一步。
原问题转换成了树上最短路问题。原问题就是:
1.$sta$和$fin$是否同根。
2.如果同根,求$sta$到$fin$的距离。
这两个问题都可以用$LCA$来解决。
如果$sta$和$fin$不存在$LCA$那么输出$NO$。
如果存在,那么计算$LCA(sta,fin)$到$sta$和$fin$分别的距离,相加即为答案。
我们可以通过辗转相除法直接计算$sta$和$fin$在二叉树中的深度。
我们用类似倍增的$LCA$的思想,先将两个节点跳到同一深度,
求$2$个深度相同的点的$LCA$,我们可以采用二分答案的方法。
对于二分答案:$LCA$到$sta$的距离$mid$,如果$sta$往上走$mid$和$fin$往上走$mid$到达的点相同,那么 答案$≤mid$
否则 答案$>mid$
如此一来,我们得到了一个$O(log^2 D)$的算法,$D$为深度。
#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
#define Max(a,b) ((a)>(b) ? (a):(b))
#define Min(a,b) ((a)<(b) ? (a):(b))
using namespace std; int depth;
struct node
{
int a,b,c;
node (){}
node (int _a,int _b,int _c) {a=_a;b=_b;c=_c;}
void sort()
{
if (b>c) swap(b,c);
if (a>b) swap(a,b);
if (b>c) swap(b,c);
}
bool operator == (const node &B)
const{
return (a==B.a)&&(b==B.b)&&(c==B.c);
}
node get_root()
{
int dep=;
node tmp=node(a,b,c);
int p=tmp.b-tmp.a,q=tmp.c-tmp.b;
while (p!=q)
{
int r;
if (p>q) r=(p-)/q,tmp.b-=r*q,tmp.c-=r*q;
else if (p<q) r=(q-)/p,tmp.a+=r*p,tmp.b+=r*p;
p=tmp.b-tmp.a,q=tmp.c-tmp.b;
dep+=r;
}
depth=dep;
return tmp;
}
node jump(int step)
{
node tmp=node(a,b,c);
int p=tmp.b-tmp.a,q=tmp.c-tmp.b;
while (p!=q&&step)
{
int r;
if (p>q)
{
r=(p-)/q;
if (r>step) r=step;
tmp.b-=r*q,tmp.c-=r*q;
}
else if (p<q)
{
r=(q-)/p;
if (r>step) r=step;
tmp.a+=r*p,tmp.b+=r*p;
}
p=tmp.b-tmp.a,q=tmp.c-tmp.b;
step-=r;
}
return tmp;
}
}sta,fin; int main()
{
scanf("%d%d%d",&sta.a,&sta.b,&sta.c);
scanf("%d%d%d",&fin.a,&fin.b,&fin.c);
sta.sort();
fin.sort();
if (sta.get_root()==fin.get_root())
{
printf("YES\n");
int dep_sta,dep_fin;
sta.get_root();dep_sta=depth;
fin.get_root();dep_fin=depth;
if (dep_sta<dep_fin) swap(sta,fin),swap(dep_sta,dep_fin);
int len=dep_sta-dep_fin;
sta=sta.jump(len);
dep_sta=dep_fin;
if (sta==fin) printf("%d\n",len);
else
{
int l=,r=dep_sta,ans=dep_sta;
while (l<=r)
{
int mid=(l+r)>>;
if (sta.jump(mid)==fin.jump(mid)) ans=mid,r=mid-;
else l=mid+;
}
printf("%d\n",len+*ans);
}
}
else printf("NO\n");
return ;
}
[BZOJ 2144]跳跳棋的更多相关文章
- 【LCA】bzoj 2144:跳跳棋
2144: 跳跳棋 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 248 Solved: 121[Submit][Status][Discuss] ...
- bzoj 2144: 跳跳棋——倍增/二分
Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...
- 【BZOJ 2144】 2144: 跳跳棋 (倍增LCA)
2144: 跳跳棋 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 642 Solved: 307 Description 跳跳棋是在一条数轴上进行的 ...
- 【bzoj2144】跳跳棋
2144: 跳跳棋 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 492 Solved: 244[Submit][Status][Discuss] ...
- BZOJ2144: 跳跳棋
传送门 神题一道. 考虑题目性质.首先对于一个状态,只存在四种情况,即最左/右边的点跳到中间,中间的点跳到左/右.而对于一个状态,显然第一种情况的两种分支不能同时存在,那么题目就可以理解为从$(a,b ...
- bzoj2144 【国家集训队2011】跳跳棋
Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...
- 跳跳棋(9018_1563)(BZOJ_2144)
题目: Hzwer的跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 某一天,黄金大神和cjy用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.他们要 ...
- BZOJ2144跳跳棋——LCA+二分
题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的 游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...
- 洛谷 P1852 [国家集训队]跳跳棋 解题报告
P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...
随机推荐
- Java基础学习笔记十七 集合框架(三)之Map
Map接口 通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下图. Collection中的集合,元素是孤立存在的(理解为单身),向集合中存 ...
- 【分布式系列之dubbo】SSM+Dubbo实战
对于传统的单一构架,也就是打成的war或者ear包部署在同一个Web容器里的构架,它虽然开发.测试.部署简单,但随着业务的不断发展,维护成本增加,可扩展性差,而且一台Tomcat的并发数在500左右, ...
- Alpha冲刺——Day2
一.合照 二.项目燃尽图 三.项目进展 图形界面基本完成 接口文档框架完成,接下来将会不断细化填充 登录界面向服务器请求数据进行ing 四.明日规划 1.注册登录接口能够完成 2.研究idea实现获得 ...
- 网络1712--c语言嵌套循环作业总结
1.助教有话说 首先,每周一篇的博客作业是很有必要的:编程的过程不仅仅是会敲几行代码.能够通过PTA就大吉大利了,你更应该做到的是梳理代码思路,通过与他人代码思路的比对,取其精华,进而不断进阶,才能逐 ...
- 百词斩APP分析
一.调研 1.第一次上手 第一次使用,可以使用微信和qq登录感觉挺不错的不然又要注册有点麻烦,在功能上,用户可以针对自身选择不同水平的英语背单词,然后有多钟方式对自己的听力和单词翻译进行提升.在u ...
- XP实验报告
实验名称:敏捷开发与XP实践 实验人员:20162309邢天岳(结对搭档20162313苑洪铭) 实验日期:2017.5.5 实验内容:1.在IDEA中使用工具(Code->Reformate ...
- ThreadLocal就是这么简单
前言 今天要研究的是ThreadLocal,这个我在一年前学习JavaWeb基础的时候接触过一次,当时在baidu搜出来的第一篇博文ThreadLocal,在评论下很多开发者认为那博主理解错误,给出了 ...
- windows 10下通过python3.6成功搭建jupyter 服务器
最近通过python学习爬虫技术,发现一个工具jupyter notebook很不错,该工具明显优势通过浏览器可以输入多行python代码,支持在线运行以及运行结果保存功能,在线验证python小模块 ...
- Mysql必须知道的知识
最近在准备面试,所以也整理了一些Mysql数据库常用的知识,供大家参考. 1.MySQL的复制原理以及流程 (1).复制基本原理流程 1. 主:binlog线程--记录下所有改变了数据库数据的语句,放 ...
- SpringMvc返回报文形式的控制-验证方法: JSON or HTML or XML
首先,请求通过accept请求头声明了支持的返回格式 然后,框架根据该请求头和代码实现(注解)选择了对应的MessageConverter处理返回! 一.验证过程 1.返回html 1.1.请求组装 ...