Submission #44044

#TimeUsernameProblemLanguageResultExecution timeMemory
44044wxh010910Fences (JOI18_fences)C++17
100 / 100
136 ms2408 KiB
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define mp make_pair #define pb push_back #define Debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef long double LD; typedef unsigned int uint; typedef pair <int, int> pii; typedef unsigned long long uLL; template <typename T> inline void Read(T &x) { char c = getchar(); bool f = false; for (x = 0; !isdigit(c); c = getchar()) { if (c == '-') { f = true; } } for (; isdigit(c); c = getchar()) { x = x * 10 + c - '0'; } if (f) { x = -x; } } template <typename T> inline bool CheckMax(T &a, const T &b) { return a < b ? a = b, true : false; } template <typename T> inline bool CheckMin(T &a, const T &b) { return a > b ? a = b, true : false; } const int N = 420; const double eps = 1e-6; const double inf = 1e9; inline int Sgn(double x) { return fabs(x) < eps ? 0 : x > 0 ? 1 : -1; } inline int Cmp(double x, double y) { return Sgn(x - y); } inline bool Mid(double l, double r, double mid) { return Cmp(l, mid) * Cmp(r, mid) <= 0; } struct Point { double x, y; Point(double _x = 0, double _y = 0) { 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); } Point operator * (const double &b) const { return Point(x * b, y * b); } 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; } double operator ^ (const Point &b) const { return x * b.y - y * b.x; } bool operator == (const Point &b) const { return !Cmp(x, b.x) && !Cmp(y, b.y); } bool operator != (const Point &b) const { return Cmp(x, b.x) || Cmp(y, b.y); } inline double Len() { return x * x + y * y; } } s(0, 0), t(1, 1000), r[4], p[N], q[N]; double ans, dis[N][N]; int n, m; inline double Dis(Point x, Point y) { return sqrt((x - y).Len()); } inline bool Mid(Point l, Point r, Point mid) { return Mid(l.x, r.x, mid.x) && Mid(l.y, r.y, mid.y); } inline Point Projection(Point p, Point q, Point x) { Point delta = q - p; return p + delta * ((x - p) * delta / delta.Len()); } inline bool IntersectInterval(double l1, double r1, double l2, double r2) { if (l1 > r1) { swap(l1, r1); } if (l2 > r2) { swap(l2, r2); } return Cmp(r1, l2) > 0 && Cmp(r2, l1) > 0; } inline bool IntersectSegment(Point l1, Point r1, Point l2, Point r2) { if (!IntersectInterval(l1.x, r1.x, l2.x, r2.x) || !IntersectInterval(l1.y, r1.y, l2.y, r2.y)) { return false; } return Sgn((l2 - l1) ^ (r2 - l1)) * Sgn((l2 - r1) ^ (r2 - r1)) < 0 && Sgn((l1 - l2) ^ (r1 - l2)) * Sgn((l1 - r2) ^ (r1 - r2)) < 0; } inline bool Check(Point x, Point y) { for (int i = 0; i < 4; ++i) { if (IntersectSegment(x, y, r[i], r[i + 1 & 3])) { return false; } } Point z = (x + y) / 2; if (z.x > -m && z.x < m && z.y > -m && z.y < m) { return false; } return true; } inline void AddEdge(int x, int y, double d) { if (IntersectSegment(x <= n ? p[x] : q[x - n], y <= n ? p[y] : q[y - n], s, t)) { CheckMin(dis[x][y + (n << 1)], d); CheckMin(dis[y][x + (n << 1)], d); CheckMin(dis[y + (n << 1)][x], d); CheckMin(dis[x + (n << 1)][y], d); } else { CheckMin(dis[x][y], d); CheckMin(dis[y][x], d); CheckMin(dis[x + (n << 1)][y + (n << 1)], d); CheckMin(dis[y + (n << 1)][x + (n << 1)], d); } } inline void AddEdge(int x, int y, double d, bool f) { if (f) { CheckMin(dis[x][y + (n << 1)], d); CheckMin(dis[y][x + (n << 1)], d); CheckMin(dis[y + (n << 1)][x], d); CheckMin(dis[x + (n << 1)][y], d); } else { CheckMin(dis[x][y], d); CheckMin(dis[y][x], d); CheckMin(dis[x + (n << 1)][y + (n << 1)], d); CheckMin(dis[y + (n << 1)][x + (n << 1)], d); } } int main() { #ifdef wxh010910 freopen("d.in", "r", stdin); #endif Read(n), Read(m), ans = m << 3; for (int i = 1; i <= n; ++i) { Read(p[i].x), Read(p[i].y), Read(q[i].x), Read(q[i].y); } r[0] = Point(m, m), r[1] = Point(m, -m), r[2] = Point(-m, -m), r[3] = Point(-m, m); for (int i = 0; i < 4; ++i) { ++n, p[n] = q[n] = r[i]; } for (int i = 1; i <= n << 2; ++i) { for (int j = 1; j <= n << 2; ++j) { dis[i][j] = i == j ? 0 : inf; } } for (int i = 1; i <= n; ++i) { AddEdge(i, i + n, 0); for (int j = 1; j < i; ++j) { if (Check(p[i], p[j])) { AddEdge(i, j, Dis(p[i], p[j])); } if (Check(p[i], q[j])) { AddEdge(i, j + n, Dis(p[i], q[j])); } if (Check(q[i], p[j])) { AddEdge(i + n, j, Dis(q[i], p[j])); } if (Check(q[i], q[j])) { AddEdge(i + n, j + n, Dis(q[i], q[j])); } Point tmp; tmp = Projection(p[j], q[j], p[i]); if (Mid(p[j], q[j], tmp) && Check(p[i], tmp)) { AddEdge(i, j, Dis(p[i], tmp), IntersectSegment(p[i], tmp, s, t) ^ IntersectSegment(p[j], tmp, s, t)); AddEdge(i, j + n, Dis(p[i], tmp), IntersectSegment(p[i], tmp, s, t) ^ IntersectSegment(q[j], tmp, s, t)); } tmp = Projection(p[j], q[j], q[i]); if (Mid(p[j], q[j], tmp) && Check(q[i], tmp)) { AddEdge(i + n, j, Dis(q[i], tmp), IntersectSegment(q[i], tmp, s, t) ^ IntersectSegment(p[j], tmp, s, t)); AddEdge(i + n, j + n, Dis(q[i], tmp), IntersectSegment(q[i], tmp, s, t) ^ IntersectSegment(q[j], tmp, s, t)); } swap(i, j); tmp = Projection(p[j], q[j], p[i]); if (Mid(p[j], q[j], tmp) && Check(p[i], tmp)) { AddEdge(i, j, Dis(p[i], tmp), IntersectSegment(p[i], tmp, s, t) ^ IntersectSegment(p[j], tmp, s, t)); AddEdge(i, j + n, Dis(p[i], tmp), IntersectSegment(p[i], tmp, s, t) ^ IntersectSegment(q[j], tmp, s, t)); } tmp = Projection(p[j], q[j], q[i]); if (Mid(p[j], q[j], tmp) && Check(q[i], tmp)) { AddEdge(i + n, j, Dis(q[i], tmp), IntersectSegment(q[i], tmp, s, t) ^ IntersectSegment(p[j], tmp, s, t)); AddEdge(i + n, j + n, Dis(q[i], tmp), IntersectSegment(q[i], tmp, s, t) ^ IntersectSegment(q[j], tmp, s, t)); } swap(i, j); } } for (int k = 1; k <= n << 2; ++k) { for (int i = 1; i <= n << 2; ++i) { for (int j = 1; j <= n << 2; ++j) { CheckMin(dis[i][j], dis[i][k] + dis[k][j]); } } } for (int i = 1; i <= n << 1; ++i) { CheckMin(ans, dis[i][i + (n << 1)]); } printf("%lf\n", ans); #ifdef wxh010910 Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC); #endif return 0; }

Compilation message (stderr)

fences.cpp: In function 'bool Check(Point, Point)':
fences.cpp:136:42: warning: suggest parentheses around '+' in operand of '&' [-Wparentheses]
     if (IntersectSegment(x, y, r[i], r[i + 1 & 3])) {
                                        ~~^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...