Skip to content
This repository was archived by the owner on Nov 29, 2020. It is now read-only.

Commit fcffeb9

Browse files
committed
GrahamScan.cpp
1 parent cded4fb commit fcffeb9

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

GrahamScan.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//
2+
// algorithm - some algorithms in "Introduction to Algorithms", third edition
3+
// Copyright (C) 2018 lxylxy123456
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as
7+
// published by the Free Software Foundation, either version 3 of the
8+
// License, or (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
#ifndef MAIN
20+
#define MAIN
21+
#define MAIN_GrahamScan
22+
#endif
23+
24+
#ifndef FUNC_GrahamScan
25+
#define FUNC_GrahamScan
26+
27+
#include <algorithm>
28+
#include "utils.h"
29+
30+
#include "SegmentsIntersect.cpp"
31+
32+
template <typename T>
33+
class PolarPoint {
34+
public:
35+
PolarPoint() {}
36+
PolarPoint(Vector<T> P, Vector<T>& P0): p(P), p0(&P0) {}
37+
bool operator<(const PolarPoint<T>& rhs) const {
38+
Vector<T> l = this->p - *p0;
39+
Vector<T> r = rhs.p - *p0;
40+
T cross = l.Cross(r);
41+
if (cross > 0)
42+
return true;
43+
else if (cross < 0)
44+
return false;
45+
else
46+
return l.Length() < r.Length();
47+
}
48+
Vector<T> p, *p0;
49+
};
50+
51+
template <typename T>
52+
void GrahamScan(std::vector<Vector<T>>& Q, std::vector<Vector<T>>& ans) {
53+
Vector<T> p0 = Q[0];
54+
std::vector<PolarPoint<T>> Q_sorted;
55+
Q_sorted.reserve(Q.size() - 1);
56+
for (auto i = Q.begin(); i != Q.end(); i++) {
57+
Vector<T> pi = *i;
58+
if (pi.y < p0.y || (pi.y == p0.y && pi.x < p0.x))
59+
std::swap(p0, pi);
60+
Q_sorted.push_back(PolarPoint<T>(pi, p0));
61+
}
62+
std::sort(Q_sorted.begin(), Q_sorted.end());
63+
std::vector<Vector<T>> P;
64+
for (auto i = Q_sorted.begin(); i != Q_sorted.end(); i++) {
65+
while (i+1 != Q_sorted.end() && (i->p - p0).Cross((i+1)->p - p0) == 0)
66+
i++;
67+
P.push_back(i->p);
68+
}
69+
ans.push_back(p0);
70+
ans.push_back(P[0]);
71+
ans.push_back(P[1]);
72+
for (size_t i = 2; i < P.size(); i++) {
73+
while (ans.size() >= 2) {
74+
Vector<T>& top = ans[ans.size() - 1];
75+
Vector<T>& next_to_top = ans[ans.size() - 2];
76+
if ((top - next_to_top).Cross(P[i] - next_to_top) > 0)
77+
break;
78+
else
79+
ans.pop_back();
80+
}
81+
ans.push_back(P[i]);
82+
}
83+
}
84+
#endif
85+
86+
#ifdef MAIN_GrahamScan
87+
int main(int argc, char *argv[]) {
88+
const size_t n = get_argv(argc, argv, 1, 200);
89+
const size_t m = get_argv(argc, argv, 2, 10);
90+
std::vector<int> b;
91+
random_integers(b, -n, n, m * 2);
92+
using T = double;
93+
std::vector<Vector<T>> Q, S;
94+
Q.reserve(m);
95+
for (size_t i = 0; i < m; i++)
96+
Q.push_back(Vector<T>(b[2 * i + 0], b[2 * i + 1]));
97+
GrahamScan(Q, S);
98+
std::cout << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>"
99+
<< std::endl;
100+
std::cout << "<svg height=\"" << 2 * n << "\" width=\"" << 2 * n << "\">"
101+
<< std::endl;
102+
std::cout << "\t<rect fill=\"#ffffff\" x=\"0\" y=\"0\" width=\"" << 2 * n
103+
<< "\" height=\"" << 2 * n << "\"/>" << std::endl;
104+
std::cout << "\t<polygon stroke=\"#000000\" fill=\"#cccccc\" points=\"";
105+
for (auto i = S.begin(); i != S.end(); i++)
106+
std::cout << n + i->x + 1 << "," << n + i->y + 1 << " ";
107+
std::cout << "\"/>" << std::endl;
108+
for (auto i = Q.begin(); i != Q.end(); i++)
109+
std::cout << "\t<circle cx=\"" << n + i->x + 1 << "\" cy=\""
110+
<< n + i->y + 1 << "\" r=\"2\"/>" << std::endl;
111+
std::cout << "</svg>" << std::endl;
112+
return 0;
113+
}
114+
#endif
115+

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
| 33 | AnySegmentsIntersect.cpp | Above | 1024 |
220220
| 33 | AnySegmentsIntersect.cpp | Below | 1024 |
221221
| 33 | AnySegmentsIntersect.cpp | Any Segments Intersect | 1025 |
222+
| 33 |
222223

223224
# Supplementary Files
224225
* `utils.h`: Utils

SegmentsIntersect.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class Vector {
3232
Vector(): x(0), y(0) {}
3333
Vector(T X, T Y): x(X), y(Y) {}
3434
T Cross(const Vector<T>& rhs) const { return x * rhs.y - y * rhs.x; }
35+
T Length() const {
36+
return x * x + y * y;
37+
}
3538
Vector<T> operator+(const Vector<T>& rhs) const {
3639
return Vector<T>(x + rhs.x, y + rhs.y);
3740
}

0 commit comments

Comments
 (0)