-
Notifications
You must be signed in to change notification settings - Fork 0
/
convex_hull.cc
117 lines (93 loc) · 2.61 KB
/
convex_hull.cc
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
/*
Copyright 2021 Ryan M. Jeong <[email protected]>
*/
// CP
#define CP do { \
std::ios::sync_with_stdio(false); \
std::cin.tie(NULL); \
} while (0)
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
// iostream
using std::cin;
using std::cout;
// vector
using std::vector;
// utility
using std::pair;
// algorithm
using std::sort;
pair<int, int> starting_point;
bool CmpCoor(const pair<int, int>&,
const pair<int, int>&);
bool CmpCcw(const pair<int, int>&,
const pair<int, int>&);
int64_t CalcCcw(const pair<int, int>&,
const pair<int, int>&,
const pair<int, int>&);
int64_t CalcSqDist(const pair<int, int>&,
const pair<int, int>&);
int main() {
CP;
int n;
cin >> n;
vector<pair<int, int>> v(n);
for (int i = 0; i < n; ++i)
cin >> v[i].first >> v[i].second;
// find the point with the lowest y-coordinate. (v[0], starting_point)
sort(v.begin(), v.end(), CmpCoor);
starting_point = v.front();
// the set of points must be sorted in increasing order of the angle they and
// the point P make with the x-axis
sort(v.begin() + 1, v.end(), CmpCcw);
// Graham's scan
vector<pair<int, int>> convex_hull;
for (const auto& p : v) {
while (convex_hull.size() >= 2) {
if (CalcCcw(convex_hull[convex_hull.size()-2], convex_hull.back(), p) > 0)
break;
convex_hull.pop_back();
}
convex_hull.push_back(p);
}
cout << convex_hull.size();
return 0;
}
bool CmpCoor(const pair<int, int>& s,
const pair<int, int>& t) {
if (s.second < t.second)
return true;
if (s.second == t.second && s.first < t.first)
return true;
return false;
}
bool CmpCcw(const pair<int, int>& s,
const pair<int, int>& t) {
int64_t res = CalcCcw(starting_point, s, t);
if (res)
return res > 0; // ccw : true, cw : false
// res = 0
int64_t dist1 = CalcSqDist(s, starting_point);
int64_t dist2 = CalcSqDist(t, starting_point);
return dist1 < dist2;
}
/* ccw : pos.
on the line : 0
cw : neg. */
int64_t CalcCcw(const pair<int, int>& a,
const pair<int, int>& b,
const pair<int, int>& c) {
int64_t u1 = b.first - a.first;
int64_t v1 = b.second - a.second;
int64_t u2 = c.first - a.first;
int64_t v2 = c.second - a.second;
return u1 * v2 - u2 * v1;
}
int64_t CalcSqDist(const pair<int, int>& s,
const pair<int, int>& t) {
int64_t diff_x = s.first - t.first;
int64_t diff_y = s.second - t.second;
return diff_x * diff_x + diff_y * diff_y;
}