ZOJ 2928 Mathematical contest in modeling(模拟退火-三维空间中心点)

时间:2022-06-01 18:32:29

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2928

题意:给出三维空间一些点。求一个点p使得p到其他点距离之和最小。

思路:对于step,每次枚举当前答案的(x,y,z)每个加或者减step,共8种情况,计算和,更新答案。




int sgn(double x)
{
    if(x>EPS) return 1;
    if(x<-EPS) return -1;
    return 0;
}


struct point
{
    double x,y;
    
        
    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
    
    void get()
    {
        RD(x); RD(y);
    }
    
    point operator+(point a)
    {
        return point(x+a.x,y+a.y);
    }
    
    point operator-(point a)
    {
        return point(x-a.x,y-a.y);
    }
    
    double operator*(point a)
    {
        return x*a.y-y*a.x;
    }
    
    point operator*(double t)
    {
        return point(x*t,y*t);
    }
    
    double operator^(point a)
    {
        return x*a.x+y*a.y;
    }
    
    double len()
    {
        return sqrt(x*x+y*y);
    }
    
    void print()
    {
        printf("%.3lf %.3lf\n",x+EPS,y+EPS);
    }
};


double len(point a)
{
    return a.len();
}


struct point3
{
    double x,y,z;
    
    point3(){}
    point3(double _x,double _y,double _z)
    {
        x=_x;
        y=_y;
        z=_z;
    }
    
    void get()
    {
        RD(x); RD(y); RD(z);
    }
    
    point3 operator+(point3 a)
    {
        return point3(x+a.x,y+a.y,z+a.z);
    }
    
    point3 operator-(point3 a)
    {
        return point3(x-a.x,y-a.y,z-a.z);
    }
    
    point3 operator*(point3 a)
    {
        return point3(y*a.z-z*a.y,z*a.x-x*a.z,x*a.y-y*a.x);
    }
    
    point3 operator*(double t)
    {
        return point3(x*t,y*t,z*t);
    }
    
    double operator^(point3 a)
    {
        return x*a.x+y*a.y+z*a.z;
    }
    
    point3 operator/(double t)
    {
        return point3(x/t,y/t,z/t);
    }
    
    double len()
    {
        return sqrt(x*x+y*y+z*z);
    }
    
    void print()
    {
        printf("%.3lf %.3lf %.3lf\n",x+EPS,y+EPS,z+EPS);
    }
};




double len(point3 a)
{
    return a.len();
}


int n;
point3 p[N],d[N];


int main()
{
    Rush(n)
    {
        int i,j,k;
        FOR1(i,n) p[i].get();
        point3 ans=point3(0,0,0),cur;
        double step=2000,Min=dinf,temp;
        int x=0;
        FOR(i,-1,1) FOR(j,-1,1) FOR(k,-1,1)
        {
            d[x++]=point3(i,j,k);
        }
        while(step>EPS)
        {
            FOR0(i,x)
            {
                temp=0; cur=ans+d[i]*step;
                FOR1(j,n) temp+=(p[j]-cur).len();
                if(sgn(temp-Min)==-1) ans=cur,Min=temp;
            }
            step*=0.99;
        }
        ans.print();
    }
}