思维题,思路比较神仙。

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

20pts:暴力BFS。

事实上,这题的解题关键就在于一次只允许跳过1颗棋子,这表明向内跳只能是距离中间棋子近的那个向内跳,跳法唯一

再看向外跳是有两种的,中间的子越过左子,或者越过右子。发现中间的子向外跳和外侧的子向内跳是一个可逆过程

假设向外跳中,向左跳是左儿子,向右跳是右儿子,那么这两个儿子有共同且唯一的父亲,也就是向内跳的操作,这样的一棵二叉树恰好与上述情形相对应。

这样,如果要判断是否有解,只要看这两个状态一直向内跳,到不能再向内(与中间子距离相等)时,也就是到了树根,如果树根相同,则有解,不同的话肯定无解。因为树根所有向外跳的状态构成了一个封闭的状态集合,不同集合无交集。

有解的话也就是求树上两点最短距离了。但是由于数据过大,没办法建树,而且一步一步跳显得很慢,$O(depth)$。为了加速,可以采用取模,在纸上画一下即可发现当两个棋子反复互相跳过的时候,实际可以取模处理,详见code。

这样,采用倍增lca思想,不断向上跳即可。$O(depth\text{log}depth)$。

WA*1:line32code手残打错。。以后敲代码敲错的情况尽量少犯

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
struct sangen{
int x,y,z;
sangen(int x=,int y=,int z=):x(x),y(y),z(z){}
inline bool operator ==(const sangen&B)const{return x==B.x&&y==B.y&&z==B.z;}
inline bool operator !=(const sangen&B)const{return (x^B.x)||(y^B.y)||(z^B.z);}
inline void shiage(){if(x>y)swap(x,y);if(x>z)swap(x,z);if(y>z)swap(y,z);}
inline void print(){printf("x=%d y=%d z=%d\n",x,y,z);}
};
inline sangen tobi(sangen A,int k){
int a=A.y-A.x,b=A.z-A.y,tmp;
while((a^b)&&k){
if(a>b)tmp=(a-)/b,k>=tmp?(k-=tmp,a%=b,!a&&(a=b)):(a-=k*b,k=),A.y=A.x+a,A.z=A.y+b;
else tmp=(b-)/a,k>=tmp?(k-=tmp,b%=a,!b&&(b=a)):(b-=k*a,k=),A.y=A.z-b,A.x=A.y-a;
}
return A;
}
int d1,d2,k;
inline sangen get_root(sangen A){
int a=A.y-A.x,b=A.z-A.y;k=;
while(a^b){
if(a>b)k+=(a-)/b,a%=b,!a&&(a=b),A.y=A.x+a,A.z=A.y+b;
else k+=(b-)/a,b%=a,!b&&(b=a),A.y=A.z-b,A.x=A.y-a;
}
return A;
}
sangen A,B,tmp1,tmp2;
inline int lca(){
if(d1<d2)B=tobi(B,d2-d1);
else A=tobi(A,d1-d2);//A.print(),B.print();
if(A==B)return abs(d1-d2);
int d=_min(d1,d2),ret=abs(d1-d2);
for(register int i=__lg(d);~i;--i){//dbg(i);
tmp1=tobi(A,<<i);tmp2=tobi(B,<<i);//tmp1.print(),tmp2.print();
if(tmp1!=tmp2)A=tmp1,B=tmp2,ret+=<<i;
}
return ret+;
} int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(A.x),read(A.y),read(A.z),read(B.x),read(B.y),read(B.z);
A.shiage(),B.shiage();
sangen tmp1=get_root(A);d1=k;
sangen tmp2=get_root(B);d2=k;//dbg(d1),dbg(d2);
if(tmp1!=tmp2){puts("NO");return ;}
printf("YES\n%d\n",lca());
return ;
}

启示:应当根据性质发现这样一种树形关系。当发现这种变换问题且数据较大,考虑图论建模

BZOJ2144 跳跳棋[建模+LCA]的更多相关文章

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

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

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

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

  3. bzoj2144 跳跳棋 二分

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

  4. BZOJ2144: 跳跳棋

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

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

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

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

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

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

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

  8. 【LCA】bzoj 2144:跳跳棋

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

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

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

随机推荐

  1. 零零散散的python笔记

    Python strip()方法 用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列. #!/usr/bin/python # -*- coding: UTF-8 -*- str = &qu ...

  2. day38 各种队列、Event事件、协程、猴子补丁

    1.各种队列 我们已经学习了队列这种存取值的方法,我们以前使用的队列是可以进行进程间通信的(IPC),但是今天学习的这两种队列是不能进行进程间通信的,只能进行线程间的通信 这两种队列分别是先进后出式队 ...

  3. BTree B+Tree

    简介 B 树是为了磁盘或其它存储设备而设计的一种多叉平衡查找树.(相对于二叉,B树每个内结点有多个分支,即多叉)B树又可以写成B-树/B-Tree,并不是B“减”树,横杠为连接符,容易被误导首先我们介 ...

  4. 【Python】【demo实验19】【练习实例】【不同位数相同阿拉伯数字组成的数之和】

    原题: 求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字.例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制. 我的代码: #!/usr/bin ...

  5. (5.15)mysql高可用系列——MHA实践

    关键词:MHA,mysql mha [1]需求 采用mysql技术,实现MHA高可用主从环境,预计未来数据量几百G MHA概念参考:MYSQL高可用技术概述 [2]环境技术架构 [2.1]MHA简介 ...

  6. 排序算法大汇总 Java实现

    一.插入类算法 排序算法的稳定性:两个大小相等的元素排序前后的相对位置不变.{31,32,2} 排序后{2,31,32},则称排序算法稳定 通用类: public class Common { pub ...

  7. LeetCode 142——环形链表II(JAVA)

    给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 - ...

  8. 安装 pybloomfilter

    1.在windows的cmd下,使用 pip install pybloomfiltermmap 命令安装,pybloomfiltermmap 时报错 ,错误信息如下 根据错误信息分析,报错原因是需要 ...

  9. Spring 注解介绍

    @Component与@Bean的区别 @Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean. @Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注 ...

  10. 搞懂Dubbo服务发布与服务注册

    一.前言 本文讲服务发布与服务注册,服务提供者本地发布服务,然后向注册中心注册服务,将服务实现类以服务接口的形式提供出去,以便服务消费者从注册中心查阅并调用服务. 本文源码分析基于org.apache ...