hdu 3830 Checkers 二分答案查找最近公共祖先

本文深入探讨了Unity3D与Unreal Engine两款顶级游戏引擎的特点与优劣,通过实际案例解析,帮助开发者选择最适合项目的引擎。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description
Little X, Little Y and Little Z are playing checkers when Little Y is annoyed. So he wants to make the chessboard much bigger. Although Little Z insists the original version, Little X stands by Little Y. After they enlarge the chessboard, the chessboard turns to an infinite line. 
The chessboard is like the Number Axes now, with each integer point able to hold a checker. At initial status there are three checkers on three different integer points , and through the game there always are three checkers. Every time, they can choose a checker A to jump across a pivot checker B to a new position(but the distance between old A and B equals to new A and B, and there should be no other checkers except B in the range [old A, new A]).
After playing for a while, they wonder whether an given status a,b,c can be transferred to x,y,z. obeying the rules. Since the checkers are considered the same, it is unnecessary for a must jump to x. 
 

Input
The first line is a,b,c.
The second line is x,y,z.
They are all integers in range (-10^9, 10^9) and the two status are valid.
 

Output
The first line is YES or NO, showing whether the transfer can be achieved.
If it is YES, then output the least steps in the second line.
 

Sample Input
1 2 3 0 3 5
 

Sample Output
YES 2
Hint
The middle checker jumps to position 0, and the status is 0 1 3 Then , the middle one jumps to 5.

//



#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//向中间走类似向根节点走,向两边走类似向二叉树左右走
//y-x=z-y 树根
struct State
{
    long long x,y,z,d;//x<y<z;  d为到根节点的距离,初始化为0
    void init()
    {
        d=0;
        if(x>y) swap(x,y);
        if(x>z) swap(x,z);
        if(y>z) swap(y,z);
    }
};
bool Equal(const State &a,const State &b)//不用判断d
{
    if(a.x==b.x&&a.y==b.y&&a.z==b.z) return true;
    return false;
}
State Root(State &a)//找a的根节点并计算出a到根节点的距离
{
    State cnt=a;
    long long l=cnt.y-cnt.x,r=cnt.z-cnt.y;
    while(l!=r)//l=r时到树根
    {
        long long t;
        if(l<r)//右面区间大,x、y向右走
        {
            if(r%l==0) t=r/l-1;
            else t=r/l;
            cnt.x+=t*l;
            cnt.y+=t*l;
        }
        else
        {
            if(l%r==0) t=l/r-1;
            else t=l/r;
            cnt.z-=t*r;
            cnt.y-=t*r;
        }
        a.d+=t;
        l=cnt.y-cnt.x,r=cnt.z-cnt.y;
    }
    return cnt;
}
State stateUp(const State &a,long long step)//a状态向上走step步,step<=a.d
{
    State cnt=a;
    cnt.d=a.d-step;
    long long l=cnt.y-cnt.x,r=cnt.z-cnt.y;
    while(step>0)
    {
        long long t;
        if(l<r)//右面区间大,x、y向右走
        {
            if(r%l==0) t=r/l-1;
            else t=r/l;
            if(t>step) t=step;
            cnt.x+=t*l;
            cnt.y+=t*l;
        }
        else
        {
            if(l%r==0) t=l/r-1;
            else t=l/r;
            if(t>step) t=step;
            cnt.z-=t*r;
            cnt.y-=t*r;
        }
        step-=t;
        l=cnt.y-cnt.x,r=cnt.z-cnt.y;
    }
    return cnt;
}
int main()
{
    State st,ed;
    while(scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&st.x,&st.y,&st.z,&ed.x,&ed.y,&ed.z)==6)
    {
        st.init();ed.init();//初始化
        State stRoot=Root(st);
        State edRoot=Root(ed);
        //st和ed根不相同
        if(!Equal(stRoot,edRoot))
        {
            printf("NO\n");
            continue;
        }
        //st和ed根相同
        //二分答案查找st和ed的最近公共祖先
        //首先把两初始状态调整到一个深度
        long long res=st.d-ed.d>0?st.d-ed.d:ed.d-st.d;
        if(st.d>ed.d) st=stateUp(st,res);
        else ed=stateUp(ed,res);
        //二分答案
        long long l=0,r=st.d;
        while(l<r)
        {
            long long mid=(l+r)/2;
            if(Equal(stateUp(st,mid),stateUp(ed,mid))) r=mid;
            else l=mid+1;
        }
        printf("YES\n%I64d\n",res+2*r);//answer=res+2*r
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值