From 88d5c82a29140aa45172a0b246f575771c571fcc Mon Sep 17 00:00:00 2001 From: Anthony Date: Tue, 1 Nov 2016 06:31:45 +0700 Subject: [PATCH] Add materials for week 12 --- README.md | 1 + week12/ConvexPolygon.cpp | 27 ++++++++++++++++++++ week12/GrahamScan.cpp | 54 ++++++++++++++++++++++++++++++++++++++++ week12/MonotoneChain.cpp | 37 +++++++++++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 week12/ConvexPolygon.cpp create mode 100644 week12/GrahamScan.cpp create mode 100644 week12/MonotoneChain.cpp diff --git a/README.md b/README.md index 466ecee..86baba4 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Materials: * Week09: Advanced Dynamic Programming * Week10: String Algorithms * Week11: SQRT Decomposition and Segment Tree with Lazy Propagation +* Week12: Geometry: Convex Hull Team: diff --git a/week12/ConvexPolygon.cpp b/week12/ConvexPolygon.cpp new file mode 100644 index 0000000..9508ba1 --- /dev/null +++ b/week12/ConvexPolygon.cpp @@ -0,0 +1,27 @@ +struct Point { + int x, y; + Point() { } + Point(int x, int y): x(x), y(y) { } +}; + +long long cross(Point o, Point a, Point b) { + return (long long) (a.x - o.x) * (b.y - o.y) - (long long) (b.x - o.x) * (a.y - o.y); +} + +double area(vector v) { + double ans = 0.0; + for (int i = 0; i < (int) v.size(); ++i) { + int nxt = (i + 1) % v.size(); + ans += cross(Point(0, 0), v[i], v[nxt]); + } + return fabs(ans) * 0.5; +} + +double perimeter(vector v) { + double ans = 0.0; + for (int i = 0; i < (int) v.size(); ++i) { + int nxt = (i + 1) % v.size(); + ans += hypot(v[i].x - v[nxt].x, v[i].y - v[nxt].y); + } + return ans; +} diff --git a/week12/GrahamScan.cpp b/week12/GrahamScan.cpp new file mode 100644 index 0000000..465d67a --- /dev/null +++ b/week12/GrahamScan.cpp @@ -0,0 +1,54 @@ +// Implementation of Graham Scan algorithm + +struct Point { + int x, y; + Point() { } + Point(int x, int y): x(x), y(y) { } + bool operator < (const Point& other) const { + // priority: lowest point + // tie: rightmost point + return (y == other.y) ? (x > other.x) : (y < other.y); + } +}; + +Point o; + +long long cross(Point o, Point a, Point b) { + return (long long) (a.x - o.x) * (b.y - o.y) - (long long) (a.y - o.y) * (b.x - o.x); +} + +bool cmp(Point a, Point b) { + long long c = cross(o, a, b); + if (c == 0LL) + return hypot(a.x - o.x, a.y - o.y) < hypot(b.x - o.x, b.y - o.y); + return c > 0; + // Angle comparison + // return (atan2(a.y - o.y, a.x - o.x) - atan2(b.y - o.y, b.x - o.x)) < 0; +} + +vector convexHull(vector v) { + vector ret; + int st = 0; + // find pivot + for (int i = 1; i < (int) v.size(); ++i) { + if (v[i] < v[st]) { + st = i; + } + } + swap(v[st], v[0]); + o = v[0]; + // sort the remaining points + sort(v.begin() + 1, v.end(), cmp); + ret.push_back(v.back()); + ret.push_back(o); + int k = 2; + for (int i = 1; i < (int) v.size(); ++i) { + while (cross(ret[k - 2], ret[k - 1], v[i]) < 0) { + ret.pop_back(); + --k; + } + ret.push_back(v[i]); + ++k; + } + return ret; +} diff --git a/week12/MonotoneChain.cpp b/week12/MonotoneChain.cpp new file mode 100644 index 0000000..dad16c0 --- /dev/null +++ b/week12/MonotoneChain.cpp @@ -0,0 +1,37 @@ +// Implementation of Andrew's Monotone Chain algorithm + +struct Point { + int x, y; + Point() { } + Point(int x, int y): x(x), y(y) { } + bool operator < (const Point& other) const { + return x < other.x; + } +}; + +long long cross(Point o, Point a, Point b) { + return (long long) (a.x - o.x) * (b.y - o.y) - (long long) (a.y - o.y) * (b.x - o.x); +} + +vector convexHull(vector v) { + vector ret; + sort(v.begin(), v.end()); + int k = 0; + for (int i = 0; i < n; ++i) { + while (k > 1 && cross(ret[k - 2], ret[k - 1], v[i]) > 0) { + --k; + ret.pop_back(); + } + ret.push_back(v[i]); + ++k; + } + for (int i = n - 2, t = k; i >= 0; --i) { + while (k > t && cross(ret[k - 2], ret[k - 1], v[i]) > 0) { + --k; + ret.pop_back(); + } + ret.push_back(v[i]); + ++k; + } + return ret; +}