题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=4260
题目大意:给你n个点的坐标,求在x轴上一点x,使得它到所有点的最大距离最小,并输出最大距离。
解题思路:由分析可知,点x从左到右移动,那么最大距离 肯定先减小后增大,即是一个下凹的曲线,求最低点的坐标,对于区间单调的函数可用二分查找零点,那么对于凹函数或者凸函数,就可以用三分确定最值点。
这个图是凸函数的极值点,凹函数的同理,只是比较时相反,取离极值最近的点,远的点被替换掉。
如上面的求极大值,第一次mid离极值近,故midd=Right;
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define eps 1e-6 ///精度
#define inf 1<<30
struct node
{
double x,y;
}p[50005];
int n;
double l,r;
double dis(double a)
{
double sum=0;
for(int i=1;i<=n;i++)
{
double dx=sqrt((p[i].x-a)*(p[i].x-a)+p[i].y*p[i].y);
sum=max(sum,dx);
}
return sum;
}
double sanfen()
{
double mid,midd,s1,s2;
while(r-l>eps)
{
mid=(l+r)/2.0;
midd=(mid+r)/2.0;
s1=dis(mid);
s2=dis(midd);
if(s1<=s2) r=midd;
else l=mid;
}
return l;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
l=inf,r=-inf;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
l=min(l,p[i].x);
r=max(r,p[i].x);
}
double ans=sanfen();
printf("%.6lf %.6lf\n",ans,dis(ans));
}
return 0;
}