hdu-3830(奇妙的想法+LCA+二分)

来源:互联网 发布:淘宝女牛仔裤 编辑:程序博客网 时间:2024/05/21 19:55

Checkers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)
Total Submission(s): 1519    Accepted Submission(s): 453


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 30 3 5
 

Sample Output
YES2
Hint
The middle checker jumps to position 0, and the status is 0 1 3Then , the middle one jumps to 5.
 
题意:一个人在玩跳棋,只有三个棋子,在一条数轴上,要求从初态到末态最少需要的步数,而规则则是这样的:一个棋子可以以另一棋子为垫子,跳到另一棋子对面,设一开始两棋子位置为x、y,跳完后为y、x1,则有x1-y==y-x。而且这里还有一个要求,就是跳跃过程中不能越过第三个棋子进行跳跃。

题解:仔细思考不难发现,其实每种棋子状态都可以一直往内跳直到无法再跳为止,然后就可以想到,对于初态和末态,如果两者都往内跳直到最后得到的根如果相同,就说明两者可以互相到达,如果根不同,则无法到达,这就解决了“YES”和“NO”的问题了。接下来在“YES”的情况下,我们要求其最小步数,我们可以先将两者到根的所需的步数统一一下,将需要步数多的先跳许多步到达和另一个一样需要相同步数到达根,然后对步数二分,只要对于当前枚举的步数,两者求得的终态相同,就令右端点为当前枚举值,反之相反。

代码:

#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <set>#include <stack>#include <map>#include <cmath>#include <functional>#include<ctime>using namespace std;typedef long long ll;typedef pair<int, int> P;const int maxn = 5e3+7;int a,b,c;int x,y,z;struct node{    int x,y,z;    node(){}    node(int _x,int _y,int _z){        if(_x>_y) swap(_x,_y);        if(_x>_z) swap(_x,_z);        if(_y>_z) swap(_y,_z);        x = _x,y = _y,z = _z;    }    bool operator == (node a){        if(a.x==x&&a.y==y&&a.z==z) return 1;        else return 0;    }    bool operator != (node a){        if(a.x==x&&a.y==y&&a.z==z) return 0;        else return 1;    }};node fin(node a,int &cnt){    while(1){        if(a.y-a.x < a.z-a.y){            int tim;            if((a.z-a.y)%(a.y-a.x)==0){                tim = (a.z-a.y)/(a.y-a.x)-1;            }            else tim = (a.z-a.y)/(a.y-a.x);            cnt+=tim;            a = node(a.y+tim*(a.y-a.x),a.y+(tim-1)*(a.y-a.x),a.z);        }        else if(a.z-a.y < a.y-a.x){            int tim;            if((a.y-a.x)%(a.z-a.y)==0){                tim = (a.y-a.x)/(a.z-a.y)-1;            }            else tim = (a.y-a.x)/(a.z-a.y);            cnt+=tim;            a = node(a.x,a.y-tim*(a.z-a.y),a.y-(tim-1)*(a.z-a.y));        }        else break;    }    return a;}node u,v;node did(node a,int cnt){    while(cnt>0){        if(a.y-a.x < a.z-a.y){            int tim;            if((a.z-a.y)%(a.y-a.x)==0){                tim = (a.z-a.y)/(a.y-a.x)-1;            }            else tim = (a.z-a.y)/(a.y-a.x);            tim = min(cnt,tim);            a = node(a.y+tim*(a.y-a.x),a.y+(tim-1)*(a.y-a.x),a.z);            cnt-=tim;        }        else if(a.z-a.y < a.y-a.x){            int tim;            if((a.y-a.x)%(a.z-a.y)==0){                tim = (a.y-a.x)/(a.z-a.y)-1;            }            else tim = (a.y-a.x)/(a.z-a.y);            tim = min(cnt,tim);            a = node(a.x,a.y-tim*(a.z-a.y),a.y-(tim-1)*(a.z-a.y));            cnt-=tim;        }    }    return a;}void solve(){    int sum1 = 0,sum2 = 0;    if(fin(u,sum1)!=fin(v,sum2)){        puts("NO");        return;    }    else puts("YES");    if(sum1<sum2){        v = did(v,sum2-sum1);    }    else{        u = did(u,sum1-sum2);    }    int l = 0,r = min(sum1,sum2);    while(r-l>1){        int mid = (l+r)>>1;        if(did(u,mid)==did(v,mid)){            r = mid;        }        else l = mid;    }    if(did(u,l)==did(v,l)){        cout<<abs(sum1-sum2)+2*l<<endl;    }    else cout<<abs(sum1-sum2)+2*r<<endl;    return;}int main(){    while(scanf("%d %d %d",&a,&b,&c)!=EOF){        u = node(a,b,c);        scanf("%d %d %d",&x,&y,&z);        v = node(x,y,z);        solve();    }    return 0;}

原创粉丝点击