码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2144: 跳跳棋——倍增/二分

时间:2017-10-08 10:19:21      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:void   包含   getch   pen   上进   mil   log   ros   技术分享   

Description

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

Input

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

Output

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

Sample Input

1 2 3
0 3 5

Sample Output

YES
2

【范围】
100% 绝对值不超过10^9
——————————————————————————————————
这道题我们发现如果从中间往两边跳的话 有两种状态 而从两边往中间跳的话只有一种状态
刚好非常符合树形状 那么我么把一个点向外跳的状态在状态树上表示为这个点的儿子
向内表示为父亲 那么如果这两个初始状态在树上有lca就有答案 这个我们可以先像倍增求lca一样
先将两个状态跳到同一深度然后再二分深度(答案)及可以辣
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::swap;
using std::min;
const int inf=0x3f3f3f3f;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int len,lena,lenb,h;
struct pos{int x,y,z;}a,b,yy,ly;
pos up(pos s,int T){
    for(len=0;T;len+=h){
        int l=s.y-s.x,r=s.z-s.y;
        if(l==r) return s;
        if(l<r) h=min(T,(r-1)/l),s.x+=h*l,s.y+=h*l;
        else h=min(T,(l-1)/r),s.y-=h*r,s.z-=h*r;
        T-=h;
    }
    return s;
}
void sort(pos &s){
    if(s.x>s.z) swap(s.x,s.z);
    if(s.x>s.y) swap(s.x,s.y);
    if(s.y>s.z) swap(s.y,s.z);
}
int main(){
    a.x=read(); a.y=read(); a.z=read(); sort(a);
    b.x=read(); b.y=read(); b.z=read(); sort(b);
    yy=up(a,inf); lena=len;
    ly=up(b,inf); lenb=len;
    if(yy.x!=ly.x||yy.y!=ly.y||yy.z!=ly.z) return puts("NO"),0;
    puts("YES");
    if(lena<lenb) swap(a,b),swap(lena,lenb);
    a=up(a,lena-lenb);
    int l=0,r=lenb;
    while(l<r){
        int mid=(l+r)>>1;
        yy=up(a,mid); ly=up(b,mid);
        if(yy.x==ly.x&&yy.y==ly.y&&yy.z==ly.z) r=mid;
        else l=mid+1;
    }
    printf("%d",(l<<1)+lena-lenb);
    return 0;
}
View Code

 

bzoj 2144: 跳跳棋——倍增/二分

标签:void   包含   getch   pen   上进   mil   log   ros   技术分享   

原文地址:http://www.cnblogs.com/lyzuikeai/p/7636496.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!