ZOJ-3593 One Person Game

/************************************************
* Author        :somniloquy
* Created Time  :2015/10/23 21:00:05
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>

using namespace std;

const int INF = 0x3fffffff;

long long ext_gcd(long long a, long long b, long long& x, long long& y)     //求特解 x y 并求 最大公约数 gcd
{
    long long ans = a;
    if(b == 0)              //递归终点
    {
        x = 1;
        y = 0;
    }
    else
    {
        ans = ext_gcd(b, a % b, x, y);      //递归
        long long temp = x;
        x = y;              //递推上一个 x y,这种写法觉得比书上容易理解。
        y = temp - a / b * y;
    }
    return ans;     //实际传值 一直都只是传 最后一个最大公约数(当b == 0时的 a)
}

long long cal(long long a, long long b, long long c)
{
    long long  x,  y;
    long long gcd = ext_gcd(a, b, x, y);
    if(c % gcd != 0)        //无解情况 c不是gcd的倍数
        return -1;
    x *= c / gcd;           //放大相同倍数
    y *= c / gcd;
    b /= gcd;           //为通解做准备
    a /= gcd;
    long long mid = (y - x) / (a + b);      //两条直线的交点 X = x + b * t 、 Y = y - a * t 同是关于 t 的一元一次方程。交点即最小值
    long long ans = (long long)INF * (long long)INF;
    long long temp;
    for(long long t = mid - 1;  t <= mid + 1; t ++)     //对交点 和 交点前后两个点 进行判断(最小值产生在附近)
    {
        if(abs(x + b * t) + abs(y - a * t) == abs(x + b * t + y - a * t))   //如果 X Y 同正 同负 则表示方向相同 可以走(a + b)来减少步数
            temp = max(abs(x + b * t), abs(y - a * t));
        else                                    //如果 X Y 异号 则表示方向相反 不能走(a + b),只能最少 |X| + |Y| 步
            temp = abs(x + b * t) + abs(y - a * t);
        ans = min(temp, ans);               //不断取最小值
    }
    return ans;
}

int main(void)
{
    long long t, A, B, a, b;
    scanf("%lld", & t);
    while(t --)
    {
        scanf("%lld %lld %lld %lld", & A, & B, & a, & b);
        long long ans = cal(a, b, B - A);
        printf("%lld\n", ans);
    }
        return 0;
}

题目

输入A B a b,分别代表 起点编号 终点编号 一步走a格 或者 一步走b格 或者 一步走(a + b)格,问最小步数。如果无解 则输出-1。

题解:

这道题的解法也是参考别人的博客。觉得这样解最简洁。
可以把通解的两个方程 X = b * t + x 、 Y = -a * t + y 分别看成 X Y关于t的线性方程。因为 b > 0,-a < 0 所以 两条直线必然相交。可以想象,若是交点为正整数,即X = Y,那只要按(a + b)方式走即是最小步数。
若不是正整数,则最小步数就在交点的左右。(详见代码)
一开始的错误就是没想通 异号的情况 纠结好久 也是脑残…- -(异号就不走(a + b)格就行….然而我是一定想走那格…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值