P1852 [国家集训队]跳跳棋

P1852 [国家集训队]跳跳棋

lca

详细解析见题解

对于每组跳棋,我们可以用一个三元组(x,y,z)表示

我们发现,这个三元组的转移具有唯一性,收束性

也就是说,把每个三元组当成点,以转移关系为边,那么可以得到一棵树

显然最短步数==lca

然后我们就可以愉快地跑lca了

但是还要加优化,就是有可能出现2个靠得近的棋子,但与另一个棋子离得远的情况

这时要跳很多次,但是可以加速,详见代码

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
struct node{
    int a[3];
    bool operator == (const node &tmp) const{return a[0]==tmp.a[0]&&a[1]==tmp.a[1]&&a[2]==tmp.a[2];}
}f,t,p1,p2;
inline int find(node x){
    int d1=x.a[1]-x.a[0],d2=x.a[2]-x.a[1]; bool c=0;
    if(d1==d2) {p1=x; return 0;}
    if(d1<d2) swap(d1,d2),c=1;
    int cnt=d1/d2,d=d1%d2; //加速跳
    if(!d) d+=d2,--cnt;
    if(c) cnt+=find((node){x.a[2]-d-d2,x.a[2]-d,x.a[2]});
    else cnt+=find((node){x.a[0],x.a[0]+d,x.a[0]+d+d2});
    return cnt;
}
inline void change(node x,int step){
    int d1=x.a[1]-x.a[0],d2=x.a[2]-x.a[1]; bool c=0;
    if(d1==d2||!step) {p1=x; return ;}
    if(d1<d2) swap(d1,d2),c=1;
    int cnt=d1/d2,d=d1%d2;
    if(!d) d+=d2,--cnt;
    if(c){
        if(step>=cnt) change((node){x.a[2]-d-d2,x.a[2]-d,x.a[2]},step-cnt);
        else change((node){x.a[2]-d-d2*(cnt-step+1),x.a[2]-d-d2*(cnt-step),x.a[2]},0);
    }
    else{
        if(step>=cnt) change((node){x.a[0],x.a[0]+d,x.a[0]+d+d2},step-cnt);
        else change((node){x.a[0],x.a[0]+d+d2*(cnt-step),x.a[0]+d+d2*(cnt-step+1)},0);
    }
}
inline bool same(int k){
    change(f,k); node r1=p1;
    change(t,k); node r2=p1;
    return r1==r2;
}
int main(){
    scanf("%d%d%d%d%d%d",&f.a[0],&f.a[1],&f.a[2],&t.a[0],&t.a[1],&t.a[2]);
    sort(f.a,f.a+3); sort(t.a,t.a+3);
    int sp1=find(f); p2=p1;
    int sp2=find(t); //求相对于树根的深度
    if(!(p1==p2)) {printf("NO"); return 0;} //树根不同
    if(sp1<sp2) swap(sp1,sp2),swap(f,t);
    int ans=sp1-sp2;
    change(f,ans); f=p1; //使两点同一深度
    int l=0,r=sp2; //二分找lca
    while(l<r){
        int mid=l+((r-l)>>1);
        if(same(mid)) r=mid;
        else l=mid+1;
    }printf("YES\n%d",(l<<1)+ans);
    return 0;
}

原文地址:https://www.cnblogs.com/kafuuchino/p/9706409.html

时间: 2024-08-26 10:15:27

P1852 [国家集训队]跳跳棋的相关文章

跳跳棋bzoj2144国家集训队

题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动成x,y,z.(棋子是没有区别的) 跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子. 写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. 输入输出格式 输入格式: 第一行包含三个整数,表示当前棋子的位置a b c.(互不相同

【资料】国家集训队论文集(1999~2014)

本文版权归ACShiryu和acvay所有,如转载请注明原作者. 国家集训队1999论文集 1.陈宏:<数据结构的选择与算法效率--从IOI98试题PICTURE谈起> 2.来煜坤:<把握本质,灵活运用--动态规划的深入探讨> 3.齐鑫:<搜索方法中的剪枝优化> 4.邵铮:<数学模型的建立.比较和应用> 5.石润婷:<隐蔽化.多维化.开放化--论当今信息学竞赛中数学建模的灵活性> 6.杨帆:<准确性.全面性.美观性--测试数据设计中的三要素

2038: [2009国家集训队]小Z的袜子(hose)+莫队入门

题目链接:2038: [2009国家集训队]小Z的袜子(hose) 题目: Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬.你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子

跳跳棋(9018_1563)(BZOJ_2144)

题目: Hzwer的跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 某一天,黄金大神和cjy用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.他们要通过最少的跳动把它们的位置移动成x,y,z.(棋子是没有区别的) 跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子. 写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. 这道题的状态是可以在树上处理的,对于一个中间到两端距离不

国家集训队2011 happiness

[试题来源] 2011中国国家集训队命题答辩 [问题描述] 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值.作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大. [输入格式] 第一行两个正整数n,m.接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学

[国家集训队2010]小Z的袜子

★★★   输入文件:hose.in   输出文件:hose.out   简单对比 时间限制:1 s   内存限制:512 MB [题目描述] 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬. 你的任务便

BZOJ 2144 跳跳棋

2144: 跳跳棋 Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动成x,y,z.(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子.  写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. Input 第一行包含三个整数,表示当前棋子的位置a

BZOJ 2038: [2009国家集训队]小Z的袜子(hose)

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7676  Solved: 3509[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只

bzoj2144 跳跳棋

Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动成x,y,z.(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子.  写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. Input 第一行包含三个整数,表示当前棋子的位置a b c.(互不相同)