poj 2142 The Balance 扩展欧几里德算法

传送门

参考博客 https://www.cnblogs.com/My-Sunshine/p/4830171.html  这个博主写的非常详细!!! O(∩_∩)O~~

一,题意:
  有两个类型的砝码,质量分别为a,b;现在要求称出质量为d的物品,
  要用多少a砝码(x)和多少b砝码(y),使得(x+y)最小。(注意:砝码位置有左右之分)。 
二,思路:
  1,砝码有左右位置之分,应对比两种情况
    i,a左b右,得出方程 ax1 - by1 = d ;
    ii,b左a右,得出方程 bx2 - ay2 = d 。 
  2,利用扩展欧几里德算法,解出(x1,y1)、(x2,y2),并求出最小x1和x2,以及相对应的y1,y2。 
  3,输出x1+y1和x2+y2 中的最小值。 
三,步骤:
  1,由题意得出两个方程
    i,ax1 - by1 = d ;
    ii,bx2 - ay2 = d 。 
  2,代入算法,解出两个方程的解(x1,y1)、(x2,y2),并求出最小x1和x2,以及相对应的y1,y2.
    (详细步骤请参照本博客poj1061或者poj2115)。
  3, 判断步骤 
    i,x1+y1最小时,输出x1,y1
    ii,x2+y2最小时,输出y2,x2。 *此处为y2在前面输出,因为x2+y2最小时,第一个输入的a对应的是y2。

#include<iostream>
#include<cmath>
#define ll long long
using namespace std;
int exgcd(int a,int b,int &x,int &y) // 板子 
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	int g=exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return g;
}
// ax-by=c 
int main()
{
	int a,b,c;
	while(cin>>a>>b>>c){
	if(a==0&&b==0&&c==0)
	break;
	
	// 求ax+by=c 的解x 
	int x,y;
	int d=exgcd(a,b,x,y);
	x=x*c/d;
	int t=b/d; 
	if(x>=0){
		x=x%t;
	}
	else{
		x=(x%t+t)%t;
	}
	y=fabs((a*x-c)/b);
	
	//求bx+ay=c 的解x
	int x1,y1;
	swap(a,b);// 交换a b的值 
	d=exgcd(a,b,x1,y1);
	x1=x1*c/d;
	t=b/d;
	if(x1>=0){
		x1=x1%t;
	}
	else{
		x1=(x1%t+t)%t;
	}
	y1=fabs((a*x1-c)/b); // abs->int型  fabs -> float型 
	
	if(x1+y1>x+y)
	{
		cout<<x<<" "<<y<<endl;
	}
	else
	{
		cout<<y1<<" "<<x1<<endl;
	}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/henucm/article/details/88078620