https://ac.nowcoder.com/acm/contest/3006/B
题目描述
由于牛牛战队经常要外出比赛,因此在全国各地建立了很多训练基地,每一个基地都有一个坐标。
这周末,牛牛队又要出去比赛了,各个比赛的赛点都在轴上。牛牛战队为了方便比赛,想找一个到达训练基地最大距离最小的地方作为比赛地。
这个问题对于牛牛战队太简单了,它就交给了你,你来帮他算一下~
思路
题解上写的是三分,二分也可以写,我是二分写的,下面说的就是二分的思路了。
二分这个最小的最大距离,首先这个比赛场地一定在轴上,对于每个训练基地而言,如果同比赛场地距离为,那么比赛场地一定在以它为圆心半径为的圆上,即是圆与坐标轴的两个交点,二分的时候距离小于等于即为合法,也就是说只要场地在两个坐标之间即为合法。可以考虑记录这个坐标区间,对于多个训练基地我们求这个坐标区间的交集,如果交集不为空,则这个合法,如果交集为空表示这个不可行。因为求距离需要开根号,因此还需要特判一下根号下的值是否为正,不是正数直接不合法。
/*************************************************************************
> File Name: B.cpp
> Author: amoscykl
> Mail: [email protected]
> Created Time: 2020年02月13日 星期四 14时52分21秒
************************************************************************/
#include
using namespace std;
const int N = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int px[N], py[N];
int n;
#define eps 1e-8
bool check(double x){
double xl, xr;
double temp = x * x - py[1] * py[1] * 1.0;
if (temp < 0)return false;
temp = sqrt(temp);
xl = px[1] * 1.0 - temp;
xr = px[1] * 1.0 + temp;
for (int i = 2; i <= n; i++){
temp = x * x - py[i] * py[i] * 1.0;
if (temp < 0)return false;
temp = sqrt(temp);
double txl = px[i] * 1.0 - temp;
double txr = px[i] * 1.0 + temp;
if (xl > txr || xr < txl){
// 没有交集
return false;
}
else{
xl = max(xl, txl);
xr = min(xr, txr);
}
}
return true;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d %d", px + i, py + i);
}
double l = 0.0;
double r = inf * 1.0;
double res = -1;
while (r - l > eps){
double mid = (l + r) / 2.0;
if (check(mid)){
res = mid;
r = mid;
}
else l = mid;
}
printf("%.6lf\n", res);
return 0;
}