The Balance
POJ - 2142
考虑到 ax+by=d
假设解为正时代表在天平左边,解为负时代表在天平右边
通过拓展欧几里得解出一组解
然后通过不断枚举找出最优解
我直接-50000 到50000 枚举了....
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
LL myabs(LL x)
{
if(x<0)return -x;
else return x;
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b)
{
x=1,y=0;
return a;
}
LL d=exgcd(b,a%b,x,y);
LL t=x;
x=y;
y=t-a/b*y;
return d;
}
int main()
{
LL a,b,d;
LL x,y;
while(cin>>a>>b>>d&& a&&b&&d)
{
LL c=exgcd(a,b,x,y);
LL t=d/c;
x*=t;
y*=t;
LL minl=99999999;
LL sum=99999999;
LL dx=b/c;
LL dy=a/c;
LL ax;
LL ay;
for(LL i=-50000;i<=50000;i++)
{
LL dx=x+i*(b/c);
LL dy=y-i*(a/c);
if(myabs(dx)+myabs(dy)<=minl&&myabs(dx)*a+myabs(dy)*b<=sum)
{
minl=myabs(dx)+myabs(dy);
sum=myabs(dx)*a+myabs(dy)*b;
ax=myabs(dx);
ay=myabs(dy);
}
}
cout<<ax<<" "<<ay<<endl;
}
}
补充:
x+y 最小说明解一定在 x=x0+t*(b/c) y=y0-t*(b/c);x=0,y=0,附近
所以令x=0 ,y=0 解得t1=-x0/(b/c) t2=y0/(a/c);
直接在t1,t2范围内枚举就好了.