• POJ 2142 The Balance (解不定方程,找最小值)


    这题实际解不定方程:ax+by=c
    只不过题目要求我们解出的x和y 满足|x|+|y|最小,当|x|+|y|相同时,满足|ax|+|by|最小。
    首先用扩展欧几里德,很容易得出x和y的解。
    一开始不妨令a>b,若a<=b,则交换a和b。
    设d=gcd(a,b),最终的
    则x=x0+b/d*t,y=y0-a/d*t
    z=|x|+|y|=|x0+b/d*t|+|y0-a/d*t|
    实际上就是求z=|a1*t+c1|+|c2-a2*t|在t取何值时最小。(a2>a1)
    首先由不定方程ax+by=c,a>0,b>0,c>0可知,x和y只有下述三种情况:
    x>0,y<0; x<0,y>0; x>0,y>0;
    那么对t分类讨论,得出:
    1.t<min(-c1/a1,c2/a2),z=-(a1+a2)t+c2-c1,单调减
    2.-c1/a1<t<c2/a2,z=(a1-a2)t+c1+c2,单调减
    3.t>max(-c1/a1,c2/a2),z=(a1+a2)t+c1-c2,单调增
    这样,我们知道当z取最小值时,t=c2/a2=y0/(a/d)=y0*d/a 附近
    接着只要在t附近几个比较一下取最小值即可。

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    
    using namespace std;
    int a,b,c;
    
    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 tmp=x;
        x=y;
        y=tmp-a/b*y;
        return d;
    }
    int main()
    {
        int number,mass;
        while(scanf("%d%d%d",&a,&b,&c)!=EOF){
            if(a==0 && b==0 && c==0)
                break;
            bool flag=false;
            if(a<b){
                flag=true;
                int tmp=a;
                a=b;
                b=tmp;
            }
            int x0,y0,x,y;
            int d=exgcd(a,b,x,y);
            int s1=b/d,s2=a/d;
            x=x*(c/d);
            y=y*(c/d);
            int t=y*d/a;
    
            number=abs(x)+abs(y);
            mass=abs(x)*a+abs(y)*b;
            int xx,yy,ansx=x,ansy=y;
            for(int i=t-10;i<=t+10;i++){
                xx=x+s1*i;
                yy=y-s2*i;
                if(abs(xx)+abs(yy)<number){
                    number=abs(xx)+abs(yy);
                    mass=abs(xx)*a+abs(yy)*b;
                    ansx=xx;
                    ansy=yy;
                }
                else if(abs(xx)+abs(yy)==number && abs(xx)*a+abs(yy)*b<mass){
                    mass=abs(xx)*a+abs(yy)*b;
                    ansx=xx;
                    ansy=yy;
                }
            }
            if(!flag)
                printf("%d %d
    ",abs(ansx),abs(ansy));
            else
                printf("%d %d
    ",abs(ansy),abs(ansx));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    iOS缓存
    哈希表
    查找
    基数排序
    归并排序
    快速排序
    redis 的高并发的理解
    springboot的理解
    使用maven命令安装jar包到本地仓库
    linux Centos7 安装docker步骤
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3557315.html
Copyright © 2020-2023  润新知