首页 > 代码库 > POJ 2142 The Balance
POJ 2142 The Balance
SOL : 扩展的欧几里德, ax+by==c
x=x0+b/d*t;
y=y0-a/d*t;
求|x|+|Y|的最小值
可以发现:
|x0+b/d*t| 单调递增 |y0-a/d*t| 单调递减
因为 a>b,所以就是说函数是凹的,先减小后增大。
显然 当y0-a/d*t==0的时候 |x|+|Y| 最小值就在那附近。
枚举几个值就能找到。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; inline int exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return a; } int d=exgcd(b,a%b,x,y); int t=x; x=y; y=t-(a/b)*y; return d; } int main() { int a,b,c,x,y,d,x1,y1,ansx,ansy; bool flag; while(~scanf("%d%d%d",&a,&b,&c),a+b+c) { flag=false; if(a<b) { flag=true; swap(a,b); } d=exgcd(a,b,x,y); x*=(c/d); y*=(c/d); int t=y*d/a; ansx=abs(x+t*b/d); ansy=abs(y-t*a/d); for(int i=1;i<5;i++) { x1=x+(t+i)*b/d; y1=y-(t+i)*a/d; x1=abs(x1); y1=abs(y1); if(x1+y1<ansx+ansy||(x1+y1==ansx+ansy&&x1*a+y1*b<ansx*a+ansy*b)) { ansx=x1; ansy=y1; } x1=x+(t-i)*b/d; y1=y-(t-i)*a/d; x1=abs(x1); y1=abs(y1); if(x1+y1<ansx+ansy||(x1+y1==ansx+ansy&&x1*a+y1*b<ansx*a+ansy*b)) { ansx=x1; ansy=y1; } } if(flag) swap(ansx,ansy); printf("%d %d\n",ansx,ansy); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。