最小距离和

题目:在一个平面坐标系中给定个点,坐标为范围的绝对值均在范围内,在轴上找一

     使得这点到所有点的距离之和最短。

 

分析:本题方法是三分,我们知道三分满足的条件是这个对象必须是单峰函数。题目要求找到最小值,那么也就是说

     这个距离之和是一个下凸函数,现在来开始证明。

 

     设要找的点的坐标为,那么设距离之和的函数为,那么得到


     

 

     继续设,对求二阶导得到

 

     

      

     在高数中我们学过下面的定理:


     定理:在区间上有二阶导数,如果,则为上的下凸函数,否则如果

          则上的上凸函数。

 

     那么得到

 

    

 

     也就是说为凸函数,也就是单峰函数,那么对于凸函数求最值我们利用三分即可。


代码:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>

using namespace std;
const int N = 100005;
const double eps = 1e-8;

struct Point
{
    double x,y;
};

Point p[N];

double dist(Point A,Point B)
{
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double sum(Point p[],int n,double x)
{
    Point t;
    t.x = x;
    t.y = 0;
    double ans = 0;
    for(int i=0;i<n;i++)
        ans += dist(p[i],t);
    return ans;
}

double Search(Point p[],int n)
{
    double l = -1e6;
    double r = 1e6;
    while(r - l > eps)
    {
        double ll = (2 * l + r) / 3;
        double rr = (l + 2 * r) / 3;
        double ans1 = sum(p,n,ll);
        double ans2 = sum(p,n,rr);
        if(ans1 > ans2) l = ll;
        else r = rr;
    }
    return l;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        printf("%.6lf\n",Search(p,n));
    }
    return 0;
}

 

 


你可能感兴趣的:(最小距离和)