poj2142

来源:互联网 发布:网络系统安全技术的有 编辑:程序博客网 时间:2024/04/27 17:20

题目链接:http://poj.org/problem?id=2142

题意:有两种类型的砝码,每种的砝码质量a和b给你,现在要求称出质量为d的物品,要求a的数量x和b的数量y最小,以及x+y的值最小。

解题思路:很明显,该题用扩展欧几里得算法。先求出ax+by=d的特解,具体球阀求法是先用扩展欧几里得算法求出ax+by=gcd(a,b)(注意a>b)。假定用扩展欧几里得算法求得的解为x,y。那么,ax+by=d的特解x=x*d/gcd,y=y*d/gcd。通过特解,我们可以求得通解:X1=X+b/gcd*t1;Y1=Y-a/gcd*t1。利用不等式的相关知识,就可以求出答案了。

#include <iostream>#include <math.h>#include <stdlib.h>#include <stdio.h>using namespace std;int exdgcd(int a,int b,int &x,int &y){    int d=a;    if(b!=0)    {        d=exdgcd(b,a%b,y,x);        y-=(a/b)*x;    }    else    {        x=1;        y=0;    }    return d;}int main(){    int a,b;    double d;    while(~scanf("%d %d %lf",&a,&b,&d)&&a+b+d)    {        int flag=0;        int x,y,gcd;        if(a<b)        {            int temp;            temp=b;            b=a;            a=temp;            flag=1;        }        gcd=exdgcd(a,b,x,y);        int X,Y,Y1,X1,X2,Y2;        X=x*d/gcd;        Y=y*d/gcd;        double t=(double)gcd/a*Y;        int t1=(int)floor(t);        X1=abs(X+b/gcd*t1);        Y1=abs(Y-a/gcd*t1);        if(t!=t1)        {            t1++;            X2=abs(X+b/gcd*t1);            Y2=abs(Y-a/gcd*t1);            if(X1+Y1<X2+Y2)            {                X=X1;                Y=Y1;            }            else if(X1+Y1>X2+Y2)            {                X=X2;                Y=Y2;            }            else            {                if(a*X1+b*Y1>a*X2+b*Y2)                {                    X=X2;                    Y=Y2;                }                else                {                    X=X1;                    Y=Y1;                }            }        }        else        {            X=X1;            Y=Y1;        }        if(flag)            cout<<Y<<' '<<X<<endl;        else            cout<<X<<' '<<Y<<endl;    }    return 0;}


 

0 0