Submission #1305831

#TimeUsernameProblemLanguageResultExecution timeMemory
1305831dashka두 개의 원 (balkan11_2circles)C++20
10 / 100
232 ms4580 KiB
#include <bits/stdc++.h>
using namespace std;

const double EPS = 1e-9;

struct Point {
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) {}
    Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }
    Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }
    Point operator*(double t) const { return Point(x * t, y * t); }
    double cross(const Point& p) const { return x * p.y - y * p.x; }
    double len() const { return sqrt(x * x + y * y); }
    Point normalize() const { double l = len(); return Point(x / l, y / l); }
    Point perpLeft() const { return Point(-y, x); }
};

double dist(const Point& a, const Point& b) { return (a - b).len(); }

int n;
vector<Point> poly;
double originalArea;

double polygonArea(const vector<Point>& p) {
    double area = 0;
    int m = p.size();
    for (int i = 0; i < m; i++)
        area += p[i].cross(p[(i + 1) % m]);
    return area / 2.0;
}

bool lineIntersect(Point p1, Point d1, Point p2, Point d2, Point& res) {
    double denom = d1.cross(d2);
    if (abs(denom) < EPS) return false;
    double t = (p2 - p1).cross(d2) / denom;
    res = p1 + d1 * t;
    return true;
}

vector<Point> shrinkPolygon(double R) {
    int m = poly.size();
    if (m < 3) return {};
    
    vector<Point> shiftedP(m), shiftedD(m);
    
    for (int i = 0; i < m; i++) {
        Point a = poly[i];
        Point b = poly[(i + 1) % m];
        Point d = b - a;
        Point normal = d.perpLeft().normalize();
        shiftedP[i] = a + normal * R;
        shiftedD[i] = d;
    }
    
    vector<Point> result;
    for (int i = 0; i < m; i++) {
        int j = (i + 1) % m;
        Point inter;
        if (lineIntersect(shiftedP[i], shiftedD[i], shiftedP[j], shiftedD[j], inter)) {
            result.push_back(inter);
        }
    }
    
    if (result.size() < 3) return {};
    
    double area = polygonArea(result);
    if (area <= EPS || area >= originalArea - EPS) {
        return {};
    }
    
    return result;
}

// Rotating calipers - O(n) convex polygon diameter
double polygonDiameter(const vector<Point>& p) {
    int m = p.size();
    if (m < 2) return 0;
    if (m == 2) return dist(p[0], p[1]);
    
    // Find antipodal pairs using rotating calipers
    int j = 1;
    double maxDist = 0;
    
    for (int i = 0; i < m; i++) {
        Point edge = p[(i + 1) % m] - p[i];
        // Advance j while triangle area increases
        while (abs(edge.cross(p[(j + 1) % m] - p[i])) > abs(edge.cross(p[j] - p[i])) + EPS) {
            j = (j + 1) % m;
        }
        maxDist = max(maxDist, dist(p[i], p[j]));
        maxDist = max(maxDist, dist(p[(i + 1) % m], p[j]));
    }
    
    return maxDist;
}

bool canFit(double R) {
    vector<Point> shrunk = shrinkPolygon(R);
    if (shrunk.size() < 2) return false;
    return polygonDiameter(shrunk) >= 2.0 * R - EPS;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    cin >> n;
    poly.resize(n);
    for (int i = 0; i < n; i++)
        cin >> poly[i].x >> poly[i].y;
    
    originalArea = polygonArea(poly);
    
    double lo = 0, hi = 2e7;
    for (int iter = 0; iter < 100; iter++) {
        double mid = (lo + hi) / 2.0;
        if (canFit(mid)) lo = mid;
        else hi = mid;
    }
    
    cout << fixed << setprecision(3) << lo << endl;
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...