跳跳棋

时间:2020-07-24 14:33:58   收藏:0   阅读:38

跳跳棋( 思维题\(\star\star\star?\))

Descrption

Input

Output

Sample Input

1 2 3
0 3 5

Sample Output

YES
2

Hint

分析

Code

#include <bits/stdc++.h>
const int Inf=0x3f3f3f3f;
struct Node{
    int x,y,z;
    void init(){
        scanf("%d%d%d",&x,&y,&z);
        if(x>y)std::swap(x,y);
        if(x>z)std::swap(x,z);
        if(y>z)std::swap(y,z);
    }
}a,b,p,q;
int step,k;
bool Equal(Node u,Node v){
  return u.x==v.x && u.y==v.y && u.z==v.z;
}
Node GetRoot(Node t,int s){//s表示往上跳多少步,找根时s==Inf
    for(step=0;s;step+=k){        
        int d1=t.y-t.x,d2=t.z-t.y;
        if(d1==d2) return t;//两边倒中间的距离相等
        if(d1<d2){//x以y为轴往右跳
            k=std::min((d2-1)/d1,s);//d2-1是避免d2是d1的倍数,跳重合了
            t.x+=k*d1;t.y+=k*d1;s-=k;//跳的过程相当于x,y向右平移了k*d1
        }
        else{//z以y为轴向左跳
            k=std::min((d1-1)/d2,s);//k表示跳的次数
            t.y-=k*d2,t.z-=k*d2,s-=k;
        }
    }
    return t;
}
void Solve(){
    a.init();b.init();//读入并排序
    p=GetRoot(a,Inf);int step1=step;//a状态往内跳直到距离相等即到根
    q=GetRoot(b,Inf);int step2=step;//b状态往内跳直到距离相等即到根
    if(!Equal(p,q)){//根的状态不一样,无论如何跳都不可能重合
        printf("NO\n");return;
    }
    if(step1<step2){//a状态离根近就交换
        std::swap(a,b);
        std::swap(step1,step2);
    }
    a=GetRoot(a,step1-step2);//a状态往内跳,直到a,b离根距离一样,类似lca
    int l=0,r=step2,mid;//二分找到a,b的最近公共祖先
    while(l<r){
        mid=(l+r)>>1;
        if(Equal(GetRoot(a,mid),GetRoot(b,mid))) r=mid;
        else l=mid+1;
    }//跳出循环时,往上跳l步正好是最近公共祖先
    printf("YES\n%d\n",(l<<1)+step1-step2);
}
int main(){
    Solve();
    return 0;
}

原文:https://www.cnblogs.com/hbhszxyb/p/13371281.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!