-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisks.cpp
134 lines (108 loc) · 3.2 KB
/
disks.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "disks.h"
ostream& operator<<(ostream& os, const Point& p)
{
os << '(' << p.x << ", " << p.y << ')';
return os ;
}
bool Point::operator==(const Point &rhs) const {
return x == rhs.x &&
y == rhs.y;
}
bool Point::operator!=(const Point &rhs) const {
return !(rhs == *this);
}
bool Point::operator<(const Point &rhs) const {
if (x < rhs.x)
return true;
if (rhs.x < x)
return false;
return y < rhs.y;
}
bool Point::operator>(const Point &rhs) const {
return rhs < *this;
}
bool Point::operator<=(const Point &rhs) const {
return !(rhs < *this);
}
bool Point::operator>=(const Point &rhs) const {
return !(*this < rhs);
}
static double isLeft(Point P0, Point P1, Point P2) {
return (P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y);
}
// Melkman's algorithm: O(n) at simple polygonal cases, O(n log(h)) otherwise
// Reference: https://maxgoldste.in/melkman/
deque<Point> getConvexHull(deque<Point>& points) {
deque<Point> result;
//if (points.size() < 3)
// return points;
if (isLeft(points[0], points[1], points[2]) > 0) {
// Right
result.emplace_back(points[0]);
result.emplace_back(points[1]);
} else {
// Left
result.emplace_back(points[1]);
result.emplace_back(points[0]);
}
result.emplace_back(points[2]);
result.emplace_front(points[2]);
//if (points.size() == 3) return points;
for (int i = 3; i < points.size(); i++) {
int s = result.size();
while (isLeft(points[i], result[0], result[1]) > 0 &&
isLeft(result[s - 2], result[s - 1], points[i]) > 0) {
i++;
if (i > points.size() - 1)
return result;
}
while (isLeft(result[s - 2], result[s - 1], points[i]) <= 0) {
result.pop_back();
s = result.size();
}
result.emplace_back(points[i]);
while (isLeft(points[i], result[0], result[1]) <= 0)
result.pop_front();
result.emplace_front(points[i]);
}
return result;
}
// Monotone Chain algorithm: O(n log(n)).
// Notice, the Melkman's algorithm is still better at the worst case.
// Reference: https://upload.wikimedia.org/wikipedia/commons/9/9a/Animation_depicting_the_Monotone_algorithm.gif
std::vector<Point> getConvexHull(std::vector<Point>& points) {
int n = points.size();
int k = 0;
std::vector<Point> H(2*n);
std::sort(points.begin(), points.end());
// Lower hull
for (int i = 0; i < n; ++i)
{
while(k >= 2 && isLeft(H[k-2], H[k-1], points[i]) <= 0)
k--;
H[k++] = points[i];
}
// Upper hull
for (int i = n-2, t = k+1; i >= 0; i--) {
while (k >= t && isLeft(H[k-2], H[k-1], points[i]) <= 0)
k--;
H[k++] = points[i];
}
H.resize(k);
return H;
}
//template<typename return_value, typename parameterT>
//size_t count_disks(func<return_value, parameterT> f, parameterT& set) {
// size_t count = 0;
//
// while (set.size() > 2) {
// auto exclude = f(set);
//
// for (auto& elem : exclude)
// erase(set, elem);
//
// ++count;
// }
//
// return count;
//}