Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- typedef long double ld;
- #define all(x) begin(x), end(x)
- #define long ll
- #define double ld
- const double EPS = 1e-9;
- bool double_less(double a, double b) {
- return a < b - EPS;
- }
- bool double_less_eq(double a, double b) {
- return a < b + EPS;
- }
- bool double_greater(double a, double b) {
- return a > b + EPS;
- }
- bool double_greater_eq(double a, double b) {
- return a > b - EPS;
- }
- bool double_equal(double a, double b) {
- return fabs(a - b) < EPS;
- }
- bool double_not_equal(double a, double b) {
- return fabs(a - b) > EPS;
- }
- struct Vector {
- double x, y;
- Vector(double a, double b) :
- x(a),
- y(b) {}
- Vector() :
- x(0),
- y(0) {}
- };
- istream &operator>>(istream &in, Vector &v) {
- return in >> v.x >> v.y;
- }
- ostream &operator<<(ostream &out, Vector v) {
- return out << v.x << ' ' << v.y;
- }
- Vector operator-(Vector a) {
- return { -a.x, - a.y };
- }
- Vector operator+(Vector a, Vector b) {
- return { a.x + b.x, a.y + b.y };
- }
- Vector operator-(Vector a, Vector b) {
- return { a.x - b.x, a.y - b.y };
- }
- Vector operator*(Vector a, double k) {
- return { a.x * k, a.y * k };
- }
- Vector operator/(Vector a, double k) {
- return { a.x / k, a.y / k };
- }
- double cross_prod(Vector a, Vector b) {
- return a.x * b.y - a.y * b.x;
- }
- double dot_prod(Vector a, Vector b) {
- return a.x * b.x + a.y * b.y;
- }
- bool operator==(Vector a, Vector b) {
- return double_equal(a.x, b.x) && double_equal(a.y, b.y);
- }
- Vector vec(Vector a, Vector b) {
- return { b.x - a.x, b.y - a.y };
- }
- double len(Vector a) {
- return hypot(a.x, a.y);
- }
- bool right_triple(Vector a, Vector b, Vector c) {
- return double_less(cross_prod(vec(a, b), vec(b, c)), 0);
- }
- bool left_triple(Vector a, Vector b, Vector c) {
- return double_greater(cross_prod(vec(a, b), vec(b, c)), 0);
- }
- bool xy_cmp(Vector a, Vector b) {
- if (double_not_equal(a.x, b.x)) {
- return a.x < b.x;
- }
- return a.y < b.y;
- }
- typedef vector<Vector> Polygon;
- Polygon convex_hull(Polygon p) {
- sort(all(p), xy_cmp);
- p.erase(unique(all(p)), p.end());
- if (p.size() < 3) {
- return p;
- }
- int n = (int)p.size();
- Polygon up(1, p[0]), down(1, p[0]);
- for (int i = 1; i < n; ++i) {
- if (i == n - 1 || right_triple(p.front(), p[i], p.back())) {
- while (up.size() >= 2 && !right_triple(up[up.size() - 2], up.back(), p[i])) {
- up.pop_back();
- }
- up.push_back(p[i]);
- }
- if (i == n - 1 || left_triple(p.front(), p[i], p.back())) {
- while (down.size() >= 2 && !left_triple(down[down.size() - 2], down.back(), p[i])) {
- down.pop_back();
- }
- down.push_back(p[i]);
- }
- }
- down.insert(down.end(), up.rbegin() + 1, up.rend() - 1);
- return down;
- }
- struct Halfplane {
- Vector a, b;
- Halfplane() {}
- Halfplane(Vector f, Vector s) :
- a(f),
- b(s) {}
- };
- const double S = 1e9;
- const double DOUBLE_INF = 1e9;
- bool contain(Halfplane a, Vector v) {
- return double_greater_eq(cross_prod(vec(a.a, a.b), vec(a.a, v)), 0);
- }
- bool collinear(Vector a, Vector b, Vector c, Vector d) {
- double A = vec(a, b).x, B = vec(a, b).y;
- double C = vec(c, d).x, D = vec(c, d).y;
- /// A / C = B / D
- return double_equal(A * D, B * C);
- }
- Vector intersect_lines(Vector a, Vector b, Vector c, Vector d) {
- double S_acd = cross_prod(vec(a, c), vec(a, d)) / 2;
- double S_bdc = cross_prod(vec(b, d), vec(b, c)) / 2;
- double S_sum = S_acd + S_bdc;
- if (double_equal(S_sum, 0)) {
- assert(false);
- return { 0, 0 };
- }
- Vector u = vec(a, b);
- u = u * S_acd / S_sum;
- return a + u;
- }
- Vector best;
- bool intersect_halfplanes(vector<Halfplane> h) {
- mt19937 randint;
- h.emplace_back(Vector(-S, 0), Vector(-S, -S));
- h.emplace_back(Vector(0, S), Vector(-S, S));
- h.emplace_back(Vector(S, 0), Vector(S, S));
- h.emplace_back(Vector(0, -S), Vector(S, -S));
- shuffle(h.begin(), h.end(), randint);
- best = { DOUBLE_INF, 0 };
- for (int i = 0; i < (int)h.size(); ++i) {
- auto &plane = h[i];
- if (contain(plane, best)) {
- continue;
- }
- double l = -DOUBLE_INF, r = +DOUBLE_INF;
- for (int j = 0; j < i; ++j) {
- if (collinear(h[j].a, h[j].b, plane.a, plane.b)) {
- if (contain(h[j], plane.a)) {
- continue;
- } else {
- return false;
- }
- }
- assert(!collinear(h[j].a, h[j].b, plane.a, plane.b));
- Vector inter = intersect_lines(h[j].a, h[j].b, plane.a, plane.b);
- double val = len(vec(plane.a, inter)) / len(vec(plane.a, plane.b));
- if (double_less(dot_prod(vec(plane.a, inter), vec(plane.a, plane.b)), 0)) {
- val *= -1;
- }
- if (contain(h[j], inter + vec(plane.a, plane.b))) {
- l = max(l, val);
- } else {
- r = min(r, val);
- }
- }
- if (double_greater(l, r)) {
- return false;
- }
- Vector A = plane.a + vec(plane.a, plane.b) * l;
- Vector B = plane.a + vec(plane.a, plane.b) * r;
- if (A.x > B.x) {
- best = A;
- } else {
- best = B;
- }
- }
- //cerr << "Best point:\t" << best << endl;
- return true;
- }
- const int N = 1e5 + 5;
- Vector a[N], b[N];
- int n;
- bool check(double w) {
- vector<Halfplane> h;
- Vector x, y, dir, nor;
- for (int i = 0; i < n; ++i) {
- dir = vec(a[i], b[i]);
- dir = dir * w / len(dir);
- nor = { -dir.y, dir.x };
- x = a[i] + nor, y = b[i] + nor;
- if (!contain(Halfplane(x, y), a[i])) {
- swap(x, y);
- }
- assert(contain(Halfplane(x, y), a[i]));
- h.emplace_back(x, y);
- x = a[i] - nor, y = b[i] - nor;
- if (!contain(Halfplane(x, y), a[i])) {
- swap(x, y);
- }
- assert(contain(Halfplane(x, y), a[i]));
- h.emplace_back(x, y);
- }
- /*cerr << "HP:" << endl;
- for (auto e : h) {
- cerr << e.a << '\t' << e.b << endl;
- }*/
- return intersect_halfplanes(h);
- }
- int main() {
- #ifdef LC
- assert(freopen("input.txt", "r", stdin));
- #endif
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cin >> n;
- for (int i = 0; i < n; ++i) {
- cin >> a[i] >> b[i];
- }
- double l = 1e-9, r = 1e5;
- for (int i = 0; i < 100; ++i) {
- double m = (l + r) / 2;
- if (check(m)) {
- r = m;
- } else {
- l = m;
- }
- }
- assert(check(r));
- cout << fixed << setprecision(8) << best << '\n';
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement