D - Drinking to turn red Gym - 102448D(计算几何,二分)

After the closing ceremony of an ICPC competition, Lucas and his friend decided to go to the hotel pool to have some magical drinks. After a while, Lucas found a magic swim ring and also realized that the swim rings had some interesting properties:
在这里插入图片描述
The swim rings are perfectly circular.
The swim rings do not move.
There may be a non-empty intersection between the swim rings in the pool.
The magic swim ring can absorb any swim ring it intersects or is tangent to. After absorption, the radius of the magic swim ring will be equal to the sum its current radius and the radius of the swim ring that was absorbed.
It was then that Lucas promised that his friend would become a grandmaster (red) at ForceCodes if he was able to solve a challenge. Obviously, his friend accepted the challenge, because he would love to become red and go screaming through the hotel so that everyone knew of his achievement. Since he was not feeling well after drinking some magic drinks, he decided to ask you to help him solve the problem.
Assuming the pool is an infinite plane and the swim rings are located at points (Xi, Yi) with radius Ri, Lucas would like to know the smallest possible radius, such that if he places a magic swim ring centered at the point (x, y), all swim rings would be absorbed by the magic ring.

Example:

In this example, the magic swim ring (red) would need a radius of at least 1 to absorb the blue swim ring. After absorption, its new radius would be equal to 4, and then it would be able to absorb the purple swim ring.

Input
The first line of input contains three integers N (0<N≤105) and x, y (−109<x,y≤109), the number of swim rings and the center of the magic swim ring.

The i-th of the next N lines contains three integers Xi, Yi (−109<Xi,Yi≤109) and Ri(1<Ri≤105), center and radius of the i-th swim ring.

Output
You must print the minimum radius the magic swim ring should have in order to solve Lucas’ challenge. Your answer is considered correct if its absolute or relative error does not exceed 10−6.

Examples
Input
2 1 1
1 7 3
5 1 3
Output
1.0000000000
Input
4 211 -458
335 369 6
-771 -753 30
193 -617 41
-27 -396 78
Output
870.3531099090

题意:
nn个圆。你当前在一个点,可以设半径变成一个圆。你的圆有一个属性,碰到了其他的圆(相交相切,题目没说包含,但是按题意应该行),就能吸收那个圆的半径。

要你给这个点设置一个最小半径使得其能覆盖所有圆。

思路:
感觉不算严格的计算几何,还是很简单的。
学长提醒了二分,然后秒了。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 1e5 + 7;

struct Point {
    double x,y,r;
}a[maxn],now;

int n;

double dis(Point a1,Point a2) {
    return sqrt((a1.x - a2.x) * (a1.x - a2.x) + (a1.y - a2.y) * (a1.y - a2.y));
}

struct Node {
    double d,r;
}b[maxn];

int cmp(Node a1,Node a2) {
    return a1.d < a2.d;
}

bool check(double mid) {
    double r = mid;
    for(int i = 1;i <= n;i++) {
        if(b[i].d - r <= 0) {
            r += b[i].r;
        }
        else return false;
    }
    return true;
}

int main() {
    
    scanf("%d%lf%lf",&n,&now.x,&now.y);
    for(int i = 1;i <= n;i++) {
        scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r);
    }
    double mx = 0;
    for(int i = 1;i <= n;i++) {
        b[i].d = dis(now,a[i]) - a[i].r;
        b[i].r = a[i].r;
        mx = max(mx,b[i].d);
    }
    sort(b + 1,b + 1 + n,cmp);
    
    double l = 0,r = mx;
    while(r - l > 1e-9) {
        double mid = (l + r) / 2;
        if(check(mid)) {
            r = mid;
        } else {
            l = mid;
        }
    }
    
    printf("%.6f\n",l);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章