POJ.2142 The Balance (拓展欧几里得)

POJ.2142 The Balance (拓展欧几里得)

题意分析

现有2种质量为a克与b克的砝码,求最少 分别用多少个(同时总质量也最小)砝码,使得能称出c克的物品。

设两种砝码分别有x个与y个,那么有ax+by=c。可用拓展欧几里得求解。

若x与y均为正数,说明在天平的同一侧,否则在不同册。

需要注意的是,求出的x与y仅为一组特解,此时需要求|x| + |y| 的最小值。根据:

这里写图片描述

可得

(2)

显然这是不好求的,但我们不妨设a>b,根据斜率关系,不难作图。

(3)

可以看出,最小值在t2附近取得,枚举附近值计算,取最小即可。

代码总览

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef int ll;
void exgcd(ll a, ll b, ll& d, ll& x, ll &y)
{
    if(!b){
        d = a,x = 1,y = 0;
    }else{
        exgcd(b, a % b, d, y, x);
        y -= x * (a / b);
    }
}
void cal(ll a, ll b,ll c)
{
    ll gcd,x,y;
    bool isswap = false;
    if(b>a){
        swap(a,b);
        isswap = true;
    }
    exgcd(a,b,gcd,x,y);
    x = x *(c/gcd);
    y = y *(c/gcd);
    int k1 = b /gcd ;
    int k2 = a /gcd ;
    int t = y * gcd / a;
    int min = fabs(x)+ fabs(y),num1 = fabs(x),num2 = fabs(y);
    for(int i = -10; i<=10;++i){
        int temp = t+i;
        if(min>fabs(x+k1*temp) + fabs(y-k2*temp)){
            min = fabs(x+k1*temp) + fabs(y-k2*temp);
            num1 = fabs(x+k1*temp);
            num2 = fabs(y-k2*temp);
        }
    }
    if(isswap) swap(num1,num2);
    printf("%d %d\n",num1,num2);
}
int main()
{
    //freopen("in.txt","r",stdin);
    ll a,b,c;
    while(scanf("%d %d %d",&a,&b,&c)){
        if(a == 0 && b == 0 && c == 0) break;
        cal(a,b,c);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值