iwts

蒟蒻咸鱼路,欢迎dalao指出错误

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

题目链接

poj-2142 The Balance

题目

The Balance
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 8015 Accepted: 3506

Description

Ms. Iyo Kiffa-Australis has a balance and only two kinds of weights to measure a dose of medicine. For example, to measure 200mg of aspirin using 300mg weights and 700mg weights, she can put one 700mg weight on the side of the medicine and three 300mg weights on the opposite side (Figure 1). Although she could put four 300mg weights on the medicine side and two 700mg weights on the other (Figure 2), she would not choose this solution because it is less convenient to use more weights. 
You are asked to help her by calculating how many weights are required. 

Input

The input is a sequence of datasets. A dataset is a line containing three positive integers a, b, and d separated by a space. The following relations hold: a != b, a <= 10000, b <= 10000, and d <= 50000. You may assume that it is possible to measure d mg using a combination of a mg and b mg weights. In other words, you need not consider "no solution" cases. 
The end of the input is indicated by a line containing three zeros separated by a space. It is not a dataset.

Output

The output should be composed of lines, each corresponding to an input dataset (a, b, d). An output line should contain two nonnegative integers x and y separated by a space. They should satisfy the following three conditions. 
  • You can measure dmg using x many amg weights and y many bmg weights. 
  • The total number of weights (x + y) is the smallest among those pairs of nonnegative integers satisfying the previous condition. 
  • The total mass of weights (ax + by) is the smallest among those pairs of nonnegative integers satisfying the previous two conditions.

No extra characters (e.g. extra spaces) should appear in the output.

Sample Input

700 300 200
500 200 300
500 200 500
275 110 330
275 110 385
648 375 4002
3 1 10000
0 0 0

Sample Output

1 3
1 1
1 0
0 3
1 1
49 74
3333 1

Source

题意

题意是给出3个值:a、b、c,a与b表示2种不同的砝码的重量,c表示一个物品的重量。物品的重量虽然给出,但是题目中是不知道的,但是砝码重量明确标出。现在将物品与砝码按照一定的规模放置,求分别需要多少件a、b物品才能够准确称出物品的具体重量。要求砝码的数量最小,如果有多种方法使得数量达到最小,则选出使用砝码总质量最少的那一种方法。保证数据一定有唯一解。

题解

首先,标准列方程问题,因为只有2种砝码,所以一定是两个变量。如果是要求平衡,那么可以得到等式:

            ax+by = c

x与y可以为负数。可以理解为,正数表示和物品在同一边,负数表示不在同一边。而x、y就代表了a、b的数量。所以一定是0或者正整数。那么这个问题也就可以化成求x、y的最小解的问题。

同时题目中描述,要求砝码总质量最小,同时要求在总质量相同的时候总数量最小。那么整个问题其实就是求|x|+|y|的最小值。在存在多解的情况下求a|x|+b|y|的最小值。

无论怎样,这个题仍然是求解集的,至少要先利用扩展欧几里德算法将通解求出。这里首先要明白一点,扩展欧几里德算法计算的实际上是:ax+by = gcd(a,b),也就是说我们首先应该进行一些转换。根据一条性质:

            a*(c/gcd(a,b))*x + b*(c/gcd(a,b))*y = c/gcd(a,b)

我们可以对x、y进行操作,从而令其由ax+by = gcd(a,b)的解集变成ax+by = c的解。即x = x*(c/gcd(a,b)),y = y*(c/gcd(a,b))。之后,我们就可以正常计算通解:x = x0 + b/gcd(a,b)*k,y = y0 - a/gcd(a,b)*k。

之后我们需要分析a|x|+b|y|的最小值问题。如果我们能够令a > b恒存在,那么y的变化率一定是比x的变化率大的。这样,可以确定k在0 = y0 - a/gcd(a,b)*k的解的范围内可以取得正确答案。

那么我们可以对k的一定范围内的值进行枚举,看那个k值代入可以令x、y得到一个最小值。

C++ AC代码0ms

#include<iostream>
#include<vector>
#include<string>
#include<math.h>
#include<algorithm>
#include<map>
#include<utility>
#include<queue>
#include<memory>
#include<stack>
#include<sstream>
#define TIME std::ios::sync_with_stdio(false)
#define LL long long
#define MAX 5
#define INF 0x3f3f3f3f

using namespace std;

int num[1010];

int exgcd(int a,int b,int &x,int &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    int ans = exgcd(b,a%b,x,y);
    int temp = y;
    y = x - (a/b)*y;
    x = temp;
    return ans;
}

int gcd(int a, int b){
    if(b == 0) return a;
    return gcd(b, a%b);
}

int main(){
    TIME;
    int a,b,d;
    while(cin >> a >> b >> d){
        if(!a && !b && !d) break;
        int x,y;
        int m = gcd(a,b);
        if(d % m != 0){  // 判定是否有解,不过看别人的代码,好像数据中没有这种情况
            cout << "no solution" << endl;
            continue;
        }
        int flag = 0;
        if(a < b){  // 确保a > b
            flag = 1;
            swap(a,b);
        }
        exgcd(a,b,x,y);
        x = x*d/m;
        y = y*d/m;  // 对解进行转化,扩展欧几里德算法是默认解的翡蜀方程
        int t = (y*m)/a;  // 求出k的值(代码中是t)
        int ans = INF;
        int x1,x2,y1,y2;
        for(int i = t-5;i <= t+5;i++){  // 枚举范围5即可
            x1 = x + (b*i)/m;
            y1 = y - (a*i)/m;
            if(abs(x1) + abs(y1) < ans){
                x2 = x1;
                y2 = y1;
                ans = abs(x1) + abs(y1);
            }
        }
        if(flag == 0){
            cout << abs(x2) << " " << abs(y2) << endl;  // 因为a、b调换了位置,所以输出顺序可能不一样
        }else{
            cout << abs(y2) << " " << abs(x2) << endl;
        }
    }

    system("pause");
    return 0;
}

阅读更多
版权声明:转载请注明原址,有错误欢迎指出 https://blog.csdn.net/iwts_24/article/details/79948567
个人分类: ACM poj题解
想对作者说点什么? 我来说一句

扩展欧几里德算法---

2008年04月15日 13KB 下载

扩展欧几里德算法c++代码

2014年08月29日 841B 下载

没有更多推荐了,返回首页

不良信息举报

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

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭