POJ 2142 The Balance 扩展欧几里得,求|x|+|y|最小

题解:先做出两个函数的图像,然后求|x|+|y|的最小值。|x|+|y|=|x0+b/d *t |+|y0-a/d *t| 这个关于t的函数的最小值应该在t零点附近(在斜率大的那条折线的零点附近,可以观察出来)。以下三种情况中,函数最小值都应该出现在B点附近。



#include<cstdio>
#include<algorithm>
using std::swap;

int Egcd ( int a, int b, int &x, int &y )
{
    int tmp, ret;
    if ( b == 0 )
    {
        x = 1, y = 0;
        return a;
    }
    ret = Egcd ( b, a%b, x, y );
    tmp = x, x = y, y = tmp-a/b*y;
    return ret;
}

int main()
{
    int a, b, d;
    while ( 1 )
    {
        scanf("%d%d%d",&a,&b,&d);
        if ( a+b+d == 0 ) break;

        bool change = false;
        if ( a < b )
        {
            swap(a,b);
            change = true;
        }

        int gc, x, y, t;
        int mmin = 99999999, x0, y0, tx, ty;
        gc = Egcd( a, b, x, y );
        t = d*y/a;
        for ( int i = t - 10; i <= t + 10; i++ )
        {
            tx = abs((d*x/gc)+(b/gc)*i);
            ty = abs((d*y/gc)-(a/gc)*i);
            if ( tx + ty < mmin )
            {
                mmin = tx + ty;
                x0 = tx, y0 = ty;
            }
        }
        if ( change ) swap(x0,y0);
        printf("%d %d\n",x0,y0);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值