题目:在一个平面坐标系中给定()个点,坐标为范围的绝对值均在范围内,在轴上找一点
使得这点到所有点的距离之和最短。
分析:本题方法是三分,我们知道三分满足的条件是这个对象必须是单峰函数。题目要求找到最小值,那么也就是说
这个距离之和是一个下凸函数,现在来开始证明。
设要找的点的坐标为,那么设距离之和的函数为,那么得到
继续设,对求二阶导得到
在高数中我们学过下面的定理:
定理:设在区间上有二阶导数,如果,则为上的下凸函数,否则如果,
则为上的上凸函数。
那么得到
也就是说为凸函数,也就是单峰函数,那么对于凸函数求最值我们利用三分即可。
代码:
#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; }
原文:http://blog.csdn.net/acdreamers/article/details/24125911