题意,给两种砝码,amg的和bmg的,和所称物品,dmg。
问怎样称,能使所用砝码数最少。如果有多种数量最少的方案,输出砝码总重量最小的方案
首先,显然是一个扩展欧几里德,求出a*x+b*y=gcd(a,b)的x和y的一组解,然后根据通解公式,找最小的|x|+|y|就行,从中选总重量最小的输出就好。
然后,就开始WA了,,,其实还是没有考虑全,对于gcd(a,b),它一定是<=min(a,b)的,当等于的时候,x和y肯定一个是0一个是1,当小于的时候,x和y必定一正一负。
所以,,,就通过通解,找到x的最小整数解,和最大负数解,然后一个向上枚举,一个向下枚举,就才能把所有的情况枚举完。。。
之前写的情况,是直接从那个解向上枚举和向下枚举,,这样,,就很可能两种情况都在同一边,然后就只会枚举到一种情况。。。
代码(很丑):
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
#define INF 99999999
int absi(int a)
{
if (a >= 0)
return a;
else
return -a;
}
int gcd(int a, int b)//普通方法
{
int m, n, r;
m = a >= b ? a : b;//m>=n
n = a<b ? a : b;
r = m%n;
while (r != 0)
{
m = n;
n = r;
r = m%n;
}
return n;
}
int ex_gcd(int a, int b, int &x, int &y)
{
int tmp, ans;
if (b == 0)
{
x = 1;
y = 0;
return a;
}
ans = ex_gcd(b, a%b, x, y);
tmp = x;
x = y;
y = tmp - (a / b)*y;
return ans;
}
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int a, b, c, d, x = 0, y = 0;
bool ans = 0;
while (scanf("%d%d%d", &a, &b, &d) != EOF && (a*b*d != 0))
{
x = 0, y = 0;
c = gcd(a, b);
ex_gcd(a, b, x, y);
//printf("%d %d %d %d\n c %d d %d\n", a, b, x, y, c, d);
int xa = d / c*x, ya = d / c*y, xb = d / c*x, yb = d / c*y;
int xt = b / c, yt = a / c;
//printf("%d %d\n", xa, ya);
int tmp = xa / xt;
xa = xa%xt;
if (xa < 0)
{
xa += xt;
ya += (tmp - 1)*yt;
}
else
{
ya += tmp*yt;
}
xb = xa - xt, yb = ya + yt;
int suma = absi(xa) + absi(ya), sumb = absi(xb) + absi(yb);
//printf("%d %d\n", xa, ya);
//printf("%d %d\n", xb, yb);
//printf("xt %d yt %d\n", xt, yt);
//printf("%d %d\n", absi(xa - xt), absi(ya + yt));
while (absi(xa - xt) + absi(ya + yt) < suma && (xa - xt > 0 || ya + yt > 0))
{
xa -= xt;
ya += yt;
suma = absi(xa) + absi(ya);
}
//printf("%d %d\n", xa, ya);
int wa = absi(xa)*a + absi(ya)*b;
//printf("%d %d\n", absi(xb + xt), absi(yb - yt));
while (absi(xb + xt) + absi(yb - yt) < sumb && (xb + xt > 0 || yb - yt > 0))
{
xb += xt;
yb -= yt;
//printf("%d %d\n", xb, yb);
sumb = absi(xb) + absi(yb);
}
//printf("%d %d\nans\n", xb, yb);
int wb = absi(xb)*a + absi(yb)*b;
if (suma < sumb)
printf("%d %d\n", absi(xa), absi(ya));
else if (sumb < suma)
printf("%d %d\n", absi(xb), absi(yb));
else if (wa < wb)
printf("%d %d\n", absi(xa), absi(ya));
else
printf("%d %d\n", absi(xb), absi(yb));
}
//while (1);
return 0;
}