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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章