ZOJ 3593 One Person Game

One Person Game

Time Limit: 2 Seconds       Memory Limit: 65536 KB

There is an interesting and simple one person game. Suppose there is a number axis under your feet. You are at point A at first and your aim is point B. There are 6 kinds of operations you can perform in one step. That is to go left or right by a,b and c, here c always equals to a+b.

You must arrive B as soon as possible. Please calculate the minimum number of steps.

 

Input

There are multiple test cases. The first line of input is an integer T(0 < T ≤ 1000) indicates the number of test cases. Then T test cases follow. Each test case is represented by a line containing four integers 4 integersABa and b, separated by spaces. (-231 ≤ AB < 231, 0 < ab < 231)

Output

For each test case, output the minimum number of steps. If it's impossible to reach point B, output "-1" instead.

Sample Input

 

2

0 1 1 2

0 1 2 4

 

Sample Output

 

1

-1

题意:意思很简单,从A走到B点,一次可以走x 步,或者 y步,或者x+y步。共有6种走法,因为前进和后退都是可以的。
现在告诉你A,B位置,x ,y值。求最小的步数。
思路:首先转化为求方程 ax+by=c的形式,题意将转化为max(x,y);这样似乎的正确的,但是不够完整。
因为这个是在x,y都是同向的前提,如果x,y不方向走,那么就应该是abc(x)+abc(y);
根据扩展欧几里得可以求出x' y'的取值范围。都是一条直线,而且它们的斜率肯定是一正一负,当它们有交叉点的时候,就是最优的。但是可能是小数。
在这个点的前后几个点进行讨论,找出最值就可以了。

#include<iostream>

#include<stdio.h>

#include<cstring>

#include<cstdlib>

#include<math.h>

using namespace std;

typedef long long LL;





LL Ex_GCD(LL a,LL b,LL &x,LL &y)

{

    if(b==0)

    {

        x=1;

        y=0;

        return a;

    }

    LL g=Ex_GCD(b,a%b,x,y);

    LL hxl=x-(a/b)*y;

    x=y;

    y=hxl;

    return g;

}

LL get(LL a,LL b)

{

    if(a*b<0)

    {

        return abs(a)+abs(b);

    }

    else return abs(a)>abs(b)? abs(a):abs(b);

}

int main()

{

    int T;

    LL A,B,a,b,g,x,y,ans,cur,c;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%lld%lld%lld%lld",&A,&B,&a,&b);

        g=Ex_GCD(a,b,x,y);

        c=A-B;

        if(c<0) c=-c;

        if(c%g!=0)

        {

            printf("-1\n");

            continue;

        }

        a=a/g;

        b=b/g;

        x=x*(c/g);

        y=y*(c/g);



        double t = (y-x)*1.0/(a+b);

        LL  K = (LL)t;



        cur = get(x+b*K,y-a*K);

        ans=cur;



        K++;

        cur=get(x+b*K,y-a*K);

        ans=min(ans,cur);



        K++;

        cur=get(x+b*K,y-a*K);

        ans=min(ans,cur);



        K=K-3;

        cur=get(x+b*K,y-a*K);

        ans=min(ans,cur);



        K=K-1;

        cur=get(x+b*K,y-a*K);

        ans=min(ans,cur);



        printf("%lld\n",ans);



    }

    return 0;

}

 

你可能感兴趣的:(game)