Hdu 3830 Checkers

Checkers

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


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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
#include <ctime>
#define LL __int64
#define eps 1e-8
using namespace std;
struct node{
	LL x,y,z,d;
};
int equal(node a,node b){
	if (a.x==b.x && a.y==b.y && a.z==b.z)
		return 1;
	return 0;
}
void cmp(node &a){
	if (a.x>a.y)
		swap(a.x,a.y);
	if (a.x>a.z)
		swap(a.x,a.z);
	if (a.y>a.z)
		swap(a.y,a.z); 
}
node find(node &a){
	node t=a;
	LL l1=t.y-t.x,l2=t.z-t.y,l;
	while (l1!=l2){
		if (l1<l2){
			l=(l2-1)/l1;
			t.x+=l*l1;
			t.y+=l*l1;
		}
		else{
			l=(l1-1)/l2;
			t.z-=l*l2;
			t.y-=l*l2;
		}
		a.d+=l;
		cmp(t);
		l1=t.y-t.x;
		l2=t.z-t.y;
	}
	return t;
}
node find1(node &a,LL s)  
{  
    node t=a;  
    while(s>0)  
    {  
        int l2=t.z-t.y,l1=t.y-t.x,l;  
        if(l1<l2)  
        {  
            l=(l2-1)/l1;  
            if(l>s) l=s;  
            t.x+=l*l1;
            t.y+=l*l1;  
        }  
        else  
        {  
            l=(l1-1)/l2;  
            if(l>s) l=s;  
            t.z-=l*l2;  
            t.y-=l*l2;  
        }  
        s-=l;  
        cmp(t);  
        l2=t.z-t.y;  
        l1=t.y-t.x;  
    }  
    return t;  
}
int main(){
	node st,ed;
	while (~scanf("%I64d%I64d%I64d %I64d%I64d%I64d",&st.x,&st.y,&st.z,&ed.x,&ed.y,&ed.z)){
		st.d=0;ed.d=0;
		cmp(st);cmp(ed);
		if (!equal(find(st),find(ed)))
			cout<<"NO"<<endl;
		else{
			LL d1=st.d,d2=ed.d;
			LL dis=max(st.d-ed.d,ed.d-st.d);
			if (st.d>ed.d) st=find1(st,dis);
			else ed=find1(ed,dis);
			LL mid,left=0,right=min(d1,d2);
			while (left<right){
				mid=(left+right)/2;
				if (equal(find1(st,mid),find1(ed,mid)))
					right=mid;
				else left=mid+1;
			}
			printf("YES\n%d\n",left*2+dis);
		}
	}
	return 0;
}

,问你能不能从起始位置通过“跳”的操作(也就是说只能隔一个球跳,不能一步一步走)达到结束位置,最少步数是多少。

求解:三个球的状态只有3种情况。一个两球距离与中间球距离相等,则跳棋只能操作中间球使其左右跳,还有两种情况就是左边距离大于右边距离所以状态多一个右边棋子可以跳。右边大亦然。我们然后可以根据这三种状态假设这是一颗二叉树。根节点就是两边距离相等的情况,再分别找初始位置和结束位置的根节点是否一致,如果一致则再求出他们的最小公共祖先的距离即可。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值