zoj 3593 One Person Game

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4677

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 toa+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 integers ABa 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,他每走一步可以选择走a米,也可以走b米,还可以走a+b米,可以往左走也可以往右走,问从A走到B最少需要走几步

可以设走x步a米的,走y部b米的,得到式子:

ax + by = B - A;

通过扩展欧几里德可得x和y

x、y的解集:X = x + b/gcd(a,b) * t;

                  Y = y - a /gcd(a,b) * t;

可将X、Y的式子看做两个直线方程,她们一个斜率为正一个斜率为负,肯定会有交点t,交点t处X==Y,此时所走的步数最少,但步数一定为整数,如果t为小数,就不能取t,需要往t的左右两边找(t - 1, t + 1)这个范围内肯定存在一个整数t使得所走步数最少,根据t可求得X、Y

(1)X、Y同号时,即方向相同,可以走a+b来减少步数,取max(X,Y)(这里可以画X、Y的坐标图来帮助理解)

(2)X、Y异号时,即方向相反,步数绝对值相加,abs(X) + abs(Y)

 

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>

using namespace std;

typedef long long ll;

const ll INF = 0x3f3f3f3f;

ll r;

void gcd(ll a, ll b, ll &x, ll &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        r = a;
        return ;
    }
    gcd(b, a % b, x, y);
    ll t = x;
    x = y;
    y = t - a / b * y;
}

ll solve(ll a, ll b, ll c)
{
    ll x, y, m;
    gcd(a, b, x, y);
    if(c % r != 0)
        return -1;
    a /= r;
    b /= r;
    x = c / r * x;
    y = c / r * y;
    ll ans = INF * INF;
    ll t = (y - x) / (a + b);
    for(ll i = t - 1 ; i <= t + 1 ; i++)
    {
        if(abs(x + b * i) + abs(y - a * i) == abs(x + b * i + y - a * i))//x、y同号
            m = max(abs(x + b * i), abs(y - a * i));
        else
            m = abs(x + b * i) + abs(y - a * i);
        ans = min(ans, m);
    }
    return ans;
}

int main()
{
    int t;
    ll A, B, a, b, c;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%lld%lld%lld%lld", &A, &B, &a, &b);
        c = B - A;
        ll ans = solve(a, b, c);
        printf("%lld\n", ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/qq2424260747/p/4919649.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值