AtCoder Beginner Contest 151 -F - Enclose All (最小圆覆盖)

Problem Statement

Given are NN points (xi,yi)(xi,yi) in a two-dimensional plane.

Find the minimum radius of a circle such that all the points are inside or on it.

Constraints

  • 2≤N≤502≤N≤50
  • 0≤xi≤10000≤xi≤1000
  • 0≤yi≤10000≤yi≤1000
  • The given NN points are all different.
  • The values in input are all integers.

Input

Input is given from Standard Input in the following format:

NN
x1x1 y1y1
::
xNxN yNyN

Output

Print the minimum radius of a circle such that all the NN points are inside or on it.

Your output will be considered correct if the absolute or relative error from our answer is at most 10−610−6.


Sample Input 1 Copy

Copy

2
0 0
1 0

Sample Output 1 Copy

Copy

0.500000000000000000

Both points are contained in the circle centered at (0.5,0)(0.5,0) with a radius of 0.50.5.

思路:

最小圆低配版,可以先去学习下这题:https://www.luogu.com.cn/problem/P1742

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <ctime>
#include <random>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n;
typedef double ld;
struct Point
{
    double x, y;
    Point() {}
    Point(double _x, double _y)
    {
        x = _x; y = _y;
    }
    Point operator +(const Point &b)const
    {
        return Point(x + b.x, y + b.y);
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x, y - b.y);
    }
    //虏忙禄媒
    double operator ^(const Point &b)const
    {
        return x * b.y - y * b.x;
    }
    Point operator *(const double &b)const
    {
        return Point(x * b , y * b);
    }
    //碌茫禄媒
    double operator *(const Point &b)const
    {
        return x * b.x + y * b.y;
    }
    //脠脝脭颅碌茫脨媒脳陋陆脟露脠B拢篓禄隆露脠脰碌拢漏拢卢潞贸x,y碌脛卤盲禄炉
    void transXY(double B)
    {
        double tx = x, ty = y;
        x = tx * cos(B) - ty * sin(B);
        y = tx * sin(B) + ty * cos(B);
    }
    ld distance(Point bb)
    {
        // chu(sqrtl((x - bb.x) * (x - bb.x) + (y - bb.y) * (y - bb.y)));
        return sqrt((x - bb.x) * (x - bb.x) + (y - bb.y) * (y - bb.y));
    }
    void show()
    {
        cout << fixed << setprecision(6) << x << "," << y << endl;
    }
};
Point a[maxn];
struct Circle
{
    Point center;
    double  r;
    Circle() {}
    Circle(Point c1, double r1) {
        center = c1;
        r = r1;
    }
};
Circle makeCircumcircle( Point &a,  Point &b,  Point &c) {
    // Mathematical algorithm from Wikipedia: Circumscribed circle
    if ( fabs((a - b) ^ (a - c)) < eps) {
        return Circle(a, 1e9);// (a,b)//(a,c)
    }
    double ox = (min(min(a.x, b.x), c.x) + max(min(a.x, b.x), c.x)) / 2;
    double oy = (min(min(a.y, b.y), c.y) + max(min(a.y, b.y), c.y)) / 2;
    double ax = a.x - ox,  ay = a.y - oy;
    double bx = b.x - ox,  by = b.y - oy;
    double cx = c.x - ox,  cy = c.y - oy;
    double d = (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by)) * 2;
    if (fabs(d) < eps)
        return Circle(a, 1e9);//
    double x = ((ax * ax + ay * ay) * (by - cy) + (bx * bx + by * by) * (cy - ay) + (cx * cx + cy * cy) * (ay - by)) / d;
    double y = ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d;
    Point p(ox + x, oy + y);
    double r = max(max(p.distance(a), p.distance(b)), p.distance(c));
    // chu(r);
    return Circle(p, r);
}

int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    gbtb;
    cin >> n;
    repd(i, 1, n)
    {
        cin >> a[i].x >> a[i].y;
    }
    mt19937 rnd(time(0));
    shuffle(a + 1, a + 1 + n, rnd);
    Circle res = Circle(a[1], 0.0);
    repd(i, 1, n)
    {
        if (res.center.distance(a[i]) > res.r)
        {
            res = Circle(a[i], 0.0);
            repd(j, 1, i - 1)
            {
                if (res.center.distance(a[j]) > res.r)
                {
                    res = Circle((a[i] + a[j]) * 0.5, a[i].distance(a[j]) * 0.5);
                    repd(k, 1, j - 1)
                    {
                        if (res.center.distance(a[k]) > res.r)
                        {
                            res = makeCircumcircle(a[i], a[j], a[k]);
                        }
                    }
                }
            }
        }
    }
    cout << fixed << setprecision(10) << res.r << endl;
    return 0;
}