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.
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.
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.
If it is YES, then output the least steps in the second line.
Sample Input
1 2 3 0 3 5
Sample Output
YES 2HintThe middle checker jumps to position 0, and the status is 0 1 3 Then , the middle one jumps to 5.
题解:仔细思考不难发现,其实每种棋子状态都可以一直往内跳直到无法再跳为止,然后就可以想到,对于初态和末态,如果两者都往内跳直到最后得到的根如果相同,就说明两者可以互相到达,如果根不同,则无法到达,这就解决了“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;
}