Challenge: Good Point

Scor cont: 70.0 / 70

Submission status: Accepted

Submission score: 1.0

Submission ID: 464757609

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/good-point/problem

Cerinta

**The scoring system for this challenge is binary. Your score is zero unless you pass all tests.**

Given $n$ *strictly convex* simple polygons and $m$ ellipses on a plane, find any point lying in their intersection. Then print two lines of output, where the first line contains the point's $x$ coordinate and the second line contains its $y$ coordinate. The point lying on the boundary of an ellipse or polygon is considered to be an *inner* point.

Input Format

The first line contains an integer, $n$, denoting the number of polygons.	
The next set of lines defines $n$ polygons, where each polygon $i$ is described as follows:

- The first line contains an integer, $v_i$, denoting the number of vertices in polygon $i$.
- Each of the $v_i$ subsequent lines contains two space-separated integers denoting the respective $x$ and $y$ coordinates for one of polygon $i$'s vertices. The list of vertices is given in *counterclockwise* order.		

The next line contains an integer, $m$, denoting the number of ellipses.		
Each of the $m$ subsequent lines contains five space-separated integers denoting the respective values of $x_1$, $y_1$, $x_2$, $y_2$, and $a$, which are the coordinates of the two focal points and the semi-major-axis for an [Ellipse](https://en.wikipedia.org/wiki/Ellipse).

Output Format

Print two lines describing an $(x, y)$ point inside the intersection. The first line must be a real number denoting the point's $x$ coordinate, and the second line must be a real number denoting its $y$ coordinate. Your answer is considered to be correct if there is a point, $(x_0, y_0)$, inside the intersection such that the distance between $(x, y)$ and $(x_0, y_0)$ is *at most* $10^{-4}$.

Constraints

- $1 \le n \le 500$
- $3 \le v_i \le 1500$
- $3 \le \sum\limits_{i=0}^{n-1} v_i \le 1500$
- $1 \le m \le 1500$
- The coordinates of points are integers in the inclusive range $[-10^4, 10^4]$.
- All semi-major-axes are integers $\le 10^4$.
- It's guaranteed that a solution exists.  
- This challenge has binary scoring.

Cod sursa

#include <bits/stdc++.h>
using namespace std;

struct Edge {
    double ax, ay;
    double dx, dy;
    double gx, gy; // gradient of violation -cross: (dy, -dx)
    double norm2;
};

struct Ellipse {
    double x1, y1, x2, y2;
    double a2; // 2a
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    vector<Edge> edges;
    edges.reserve(2000);

    double sx = 0.0, sy = 0.0;
    int sc = 0;

    for (int pi = 0; pi < n; ++pi) {
        int v;
        cin >> v;
        vector<pair<double, double>> p(v);
        for (int i = 0; i < v; ++i) {
            cin >> p[i].first >> p[i].second;
            sx += p[i].first;
            sy += p[i].second;
            ++sc;
        }
        for (int i = 0; i < v; ++i) {
            auto A = p[i];
            auto B = p[(i + 1) % v];
            double dx = B.first - A.first;
            double dy = B.second - A.second;
            double norm2 = dx * dx + dy * dy;
            edges.push_back({A.first, A.second, dx, dy, dy, -dx, norm2});
        }
    }

    int m;
    cin >> m;
    vector<Ellipse> ell(m);
    for (int i = 0; i < m; ++i) {
        double x1, y1, x2, y2, a;
        cin >> x1 >> y1 >> x2 >> y2 >> a;
        ell[i] = {x1, y1, x2, y2, 2.0 * a};
    }

    auto maxViolation = [&](double x, double y) {
        double mv = 0.0;
        for (const auto &e : edges) {
            double cross = e.dx * (y - e.ay) - e.dy * (x - e.ax);
            if (cross < 0.0) mv = max(mv, -cross);
        }
        for (const auto &e : ell) {
            double d1 = hypot(x - e.x1, y - e.y1);
            double d2 = hypot(x - e.x2, y - e.y2);
            mv = max(mv, d1 + d2 - e.a2);
        }
        return mv;
    };

    double x = (sc ? sx / sc : 0.0);
    double y = (sc ? sy / sc : 0.0);

    const double EPS = 1e-10;

    // Phase 1: cyclic subgradient projections.
    for (int it = 0; it < 30000; ++it) {
        double mv = 0.0;

        for (const auto &e : edges) {
            double cross = e.dx * (y - e.ay) - e.dy * (x - e.ax);
            if (cross < 0.0) {
                double v = -cross;
                mv = max(mv, v);
                double step = v / e.norm2;
                x -= step * e.gx;
                y -= step * e.gy;
            }
        }

        for (const auto &e : ell) {
            double vx1 = x - e.x1, vy1 = y - e.y1;
            double vx2 = x - e.x2, vy2 = y - e.y2;
            double d1 = hypot(vx1, vy1);
            double d2 = hypot(vx2, vy2);
            double v = d1 + d2 - e.a2;
            if (v > 0.0) {
                mv = max(mv, v);
                double gx = 0.0, gy = 0.0;
                if (d1 > 1e-15) {
                    gx += vx1 / d1;
                    gy += vy1 / d1;
                }
                if (d2 > 1e-15) {
                    gx += vx2 / d2;
                    gy += vy2 / d2;
                }
                double norm2 = gx * gx + gy * gy;
                if (norm2 > 1e-18) {
                    double step = v / norm2;
                    x -= step * gx;
                    y -= step * gy;
                }
            }
        }

        if (mv <= EPS) break;
    }

    // Phase 2 fallback: project on the most violated constraint.
    if (maxViolation(x, y) > 1e-8) {
        for (int it = 0; it < 200000; ++it) {
            double bestV = -1.0;
            int bestType = -1; // 0=edge, 1=ellipse
            int bestIdx = -1;

            for (int i = 0; i < (int)edges.size(); ++i) {
                const auto &e = edges[i];
                double cross = e.dx * (y - e.ay) - e.dy * (x - e.ax);
                if (-cross > bestV) {
                    bestV = -cross;
                    bestType = 0;
                    bestIdx = i;
                }
            }

            for (int i = 0; i < (int)ell.size(); ++i) {
                const auto &e = ell[i];
                double d1 = hypot(x - e.x1, y - e.y1);
                double d2 = hypot(x - e.x2, y - e.y2);
                double v = d1 + d2 - e.a2;
                if (v > bestV) {
                    bestV = v;
                    bestType = 1;
                    bestIdx = i;
                }
            }

            if (bestV <= EPS) break;

            if (bestType == 0) {
                const auto &e = edges[bestIdx];
                double step = bestV / e.norm2;
                x -= step * e.gx;
                y -= step * e.gy;
            } else {
                const auto &e = ell[bestIdx];
                double vx1 = x - e.x1, vy1 = y - e.y1;
                double vx2 = x - e.x2, vy2 = y - e.y2;
                double d1 = hypot(vx1, vy1);
                double d2 = hypot(vx2, vy2);
                double gx = 0.0, gy = 0.0;
                if (d1 > 1e-15) {
                    gx += vx1 / d1;
                    gy += vy1 / d1;
                }
                if (d2 > 1e-15) {
                    gx += vx2 / d2;
                    gy += vy2 / d2;
                }
                double norm2 = gx * gx + gy * gy;
                if (norm2 > 1e-18) {
                    double step = bestV / norm2;
                    x -= step * gx;
                    y -= step * gy;
                }
            }
        }
    }

    cout.setf(std::ios::fixed);
    cout << setprecision(10) << x << '\n' << setprecision(10) << y << '\n';
    return 0;
}
HackerRank Geometry – Good Point