P1497[洛谷]P1852跳跳棋

P1497[洛谷]P1852跳跳棋

标签(空格分隔): 信息 图论 二分 洛谷

考题,看到就觉得是不可能写出来的那种,于是打了个bfs直接走人。
考完之后听吕大佬讲过之后觉得此题可谓绝妙啊%%%
屁颠屁颠地跑去写之后才发现思路出来了代码也并不好些。

题面

看到觉得和倒油很像,一看数据范围吓死人, 10 9 ,搜索不可能了
看着和log有关,仔细分析一下发现可以把这个叫做跳跳棋的游戏的一步棋看成一个岔路口,一共有三条分支
1.中间的棋子往左边跳
2.中间打棋子往右边跳
3.左边或者右边的靠中间棋子近的往中间跳
(因为跳棋不可以跨过一个棋子)
我们不妨把第三跳分支看成主干,一个二叉树的模型就出来了。
题目中的abc,xyz就是其中的一个结点,那么我们要求是否连通,只要判断它们的根结点是不是相同,如何确定一个点是否为根结点呢?只要确保它没有父亲结点就是根结点了,不难发现满足相邻两个结点的距离相等的点就是没有父亲的结点即根结点了。
要求最少步数,直接跑lca就好了,由于这是个抽象的树,结点不全,在这里最好用二分直接求解。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int x,y,z,s1,s2,s3,t1,t2,t3,a1,a2,a3,b1,b2,b3;
int first(int x1,int x2,int x3)
{
    return min(min(x1,x2),x3);
}
int third(int x1,int x2,int x3)
{
    return max(max(x1,x2),x3);
}
int second(int x1,int x2,int x3)
{
    return x1+x2+x3-first(x1,x2,x3)-third(x1,x2,x3);
}
int dfs(int a,int b,int c)
{
    if(b-a==c-b)
    {
        b1=a,b2=b,b3=c;
        return 0;
    }
    if(b-a<c-b)
    {
        if((c-b)%(b-a))
            return dfs(c-(c-b)%(b-a)-(b-a),c-(c-b)%(b-a),c)+(c-b)/(b-a);
        else
            return dfs(c-2*(b-a),c-(b-a),c)+(c-b)/(b-a)-1;
    }
    if((b-a)%(c-b))
        return dfs(a,a+(b-a)%(c-b),a+(b-a)%(c-b)+c-b)+(b-a)/(c-b);
    else
        return dfs(a,a+(c-b),a+2*(c-b))+(b-a)/(c-b)-1;
}
void hehe(int a,int b,int c,int value,int times)
{
    //cout<<"*";
    if(b-a==c-b||value==times)
    {
        s1=a,s2=b,s3=c;
        return ;
    }
    if(b-a<c-b)
    {
        if((c-b)%(b-a))
        {
            if(value-times<(c-b)/(b-a))
                hehe(a+(value-times)*(b-a),b+(value-times)*(b-a),c,value,value);
            else
                hehe(c-(c-b)%(b-a)-(b-a),c-(c-b)%(b-a),c,value,times+(c-b)/(b-a));
        }
        else
        {
            if(value-times<(c-b)/(b-a)-1)
                hehe(a+(value-times)*(b-a),b+(value-times)*(b-a),c,value,value);
            else
                hehe(c-2*(b-a),c-(b-a),c,value,times+(c-b)/(b-a)-1);
        }
        return ;
    }
    if((b-a)%(c-b))
    {
        if(value-times<(b-a)/(c-b))
            hehe(a,b-(value-times)*(c-b),c-(value-times)*(c-b),value,value);
        else
            hehe(a,a+(b-a)%(c-b),a+(b-a)%(c-b)+c-b,value,times+(b-a)/(c-b));
    }
    else
    {
        if(value-times<(b-a)/(c-b)-1)
            hehe(a,b-(value-times)*(c-b),c-(value-times)*(c-b),value,value);
        else
            hehe(a,a+(c-b),a+2*(c-b),value,times+(b-a)/(c-b)-1);
    }
}
int divide(int l,int r)
{
    //cout<<l<<" "<<r<<" ";
    if(l==r)return l;
    int mid=(l+r)/2;
    hehe(a1,a2,a3,mid,0);
    t1=s1,t2=s2,t3=s3;
    hehe(b1,b2,b3,mid,0);
    //cout<<t1<<" "<<t2<<" "<<t3<<" "<<s1<<" "<<s2<<" "<<s3<<endl;
    if(t1==s1&&t2==s2&&t3==s3)
        return divide(l,mid);
    else
        return divide(mid+1,r);
}
int main()
{
    int a,b,c;
    cin>>a>>b>>c;
    cin>>x>>y>>z;
    int len1=dfs(first(a,b,c),second(a,b,c),third(a,b,c));a1=b1,a2=b2,a3=b3;
    int len2=dfs(first(x,y,z),second(x,y,z),third(x,y,z));
    if(a1!=b1||a2!=b2||a3!=b3)
    {
        cout<<"NO";
        return 0;
    }
    cout<<"YES"<<endl;
    a1=first(a,b,c),a2=second(a,b,c),a3=third(a,b,c),b1=first(x,y,z),b2=second(x,y,z),b3=third(x,y,z);
    if(len1>len2)
    {
        swap(a1,b1);swap(a2,b2);swap(a3,b3);
        swap(len1,len2);
    }
    //cout<<len1<<len2<<endl;
    hehe(b1,b2,b3,len2-len1,0);
    b1=s1,b2=s2,b3=s3;
    //cout<<a1<<" "<<a2<<" "<<a3<<" "<<b1<<" "<<b2<<" "<<b3<<endl;
    cout<<len2-len1+2*divide(0,len1);
    return 0;
}

代码有点长,能ac就好。。。

猜你喜欢

转载自blog.csdn.net/qq_42805868/article/details/81227362
今日推荐