zoukankan      html  css  js  c++  java
  • POJ 2142 The Balance ★ (不定方程 ax+by=c 的|x|+|y|最小解)

    题目大意:给定两个重a,b的砝码来称一个d重的东西,求出a,b所需的数量x,y要求x+y最小,当相等时ax+by最小. 题目链接http://poj.org/problem?id=2142   显然就是解方程ax + by = d ,当x,y都>0时在一侧,异号时便异侧. 那么剩下的问题就是如何寻找|x|+|y|的最小解了.   我们来看方程的通解: x = x0 + kb y = y0 - ka   如果我们对函数方程还熟悉的话就会发现这是一条平面直角坐标系内的直线: 未命名     于是我们可发现|x|+|y|最小值一定在坐标轴附近的整点(枚举一下坐标轴附近的正点和负点比较一下就行了……),至于是x轴还是y轴要看a大还是b大.  
    #include 
    #include 
    using namespace std;
    int abs(int a){
        return a>0?a:-a;
    }
    int gcd(int a, int b){
        return b?gcd(b, a%b):a;
    }
    void ext_gcd(int a, int b, int &x, int &y){
        if (b == 0){
            x = 1;
            y = 0;
            return ;
        }
        ext_gcd(b, a%b, x, y);
        int tmp = x;
        x = y;
        y = tmp - a/b*y;
        return ;
    }
    void fuck(int a, int b, int c, int &minx, int &miny){
        int g = gcd(a,b);
        a /= g;
        b /= g;
        c /= g;
        int x0, y0;
        ext_gcd(a, b, x0, y0);
        x0 *= c;
        y0 *= c;
    
        miny = minx = (1 << 25);
        if (a < b){
            int tmp_x = (x0%b+b) % b;
            int k = (tmp_x - x0) / b;
            x0 = tmp_x;
            y0 = y0 - k*a;
            for (int p = 0; p >= -1; p --){
                x0 = x0 + p*b;
                y0 = y0 - p*a;
                if (abs(x0)+ abs(y0) < minx + miny){
                    minx = abs(x0);
                    miny = abs(y0);
                }
                else if (abs(x0)+ abs(y0) == minx + miny)
                    if (abs(x0)*a + abs(y0)*b < minx*a + miny*b){
                        minx = abs(x0);
                        miny = abs(y0);
                    }
            }
        }
        else{
            int tmp_y = (y0%a+a) % a;
            int k = (tmp_y - y0) / a;
            y0 = tmp_y;
            x0 = x0 - k*b;
            for (int p = 0; p <= 1; p ++){
                x0 = x0 + p*b;
                y0 = y0 - p*a;
                if (abs(x0)+ abs(y0) < minx + miny){
                    minx = abs(x0);
                    miny = abs(y0);
                }
                else if (abs(x0)+ abs(y0) == minx + miny)
                    if (abs(x0)*a + abs(y0)*b < minx*a + miny*b){
                        minx = abs(x0);
                        miny = abs(y0);
                    }
            }
        }
    
    }
    int main(){
        int a, b, d;
        while(scanf("%d%d%d", &a, &b, &d) == 3){
            if (a + b + d == 0)
                break;
            int minx, miny;
            fuck(a, b, d, minx, miny);
            printf("%d %d\n", minx, miny);
        }
        return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    高仿IOS下拉刷新的粘虫效果
    CSDN无耻,亿赛通无耻
    2014年10月Android面试总结
    HttpClient和HttpURLConnection的使用和区别(下)
    HttpClient和HttpURLConnection的使用和区别(上)
    Gson简单使用
    Android PowerImageView实现,可以播放动画的强大ImageView
    Android访问网络,使用HttpURLConnection还是HttpClient?
    自定义android ProgressDialog
    NPOI导Excel样式设置
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114208.html
Copyright © 2011-2022 走看看