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

Commit 6b3013b

Browse files
committed
ClosestPairPoints.cpp
1 parent f795a6b commit 6b3013b

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed

ClosestPairPoints.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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_ClosestPairPoints
22+
#endif
23+
24+
#ifndef FUNC_ClosestPairPoints
25+
#define FUNC_ClosestPairPoints
26+
27+
#include <algorithm>
28+
#include <cassert>
29+
#include <unordered_set>
30+
#include "utils.h"
31+
32+
#include "SegmentsIntersect.cpp"
33+
34+
#define uset_vec typename std::unordered_set<Vector<T>, VectorHash<T>>
35+
36+
template <typename T>
37+
class VecPair {
38+
public:
39+
VecPair(): cached(false) {}
40+
VecPair(Vector<T> A, Vector<T> B): a(A), b(B), cached(false) {}
41+
T Dist() const {
42+
if (!cached) {
43+
T dx = a.x - b.x, dy = a.y - b.y;
44+
cache = dx * dx + dy * dy;
45+
cached = true;
46+
}
47+
return cache;
48+
}
49+
Vector<T> a, b;
50+
mutable T cache;
51+
mutable bool cached;
52+
};
53+
54+
template <typename T>
55+
VecPair<T> ClosestPairPoints(uset_vec& P, std::vector<Vector<T>>& X,
56+
std::vector<Vector<T>>& Y) {
57+
assert(P.size() == X.size() && X.size() == Y.size());
58+
if (X.size() <= 3) {
59+
VecPair<T> ans(X[0], X[1]);
60+
if (X.size() == 3) {
61+
VecPair<T> ans1(X[0], X[2]), ans2(X[1], X[2]);
62+
if (ans.Dist() > ans1.Dist())
63+
ans = ans1;
64+
if (ans.Dist() > ans2.Dist())
65+
ans = ans2;
66+
}
67+
return ans;
68+
}
69+
size_t index = X.size() / 2;
70+
T l = X[index].x;
71+
uset_vec PL(X.begin(), X.begin() + index), PR(X.begin() + index, X.end());
72+
std::vector<Vector<T>> XL(X.begin(), X.begin() + index);
73+
std::vector<Vector<T>> XR(X.begin() + index, X.end());
74+
std::vector<Vector<T>> YL, YR;
75+
for (auto i = Y.begin(); i != Y.end(); i++) {
76+
if (PL.find(*i) != PL.end())
77+
YL.push_back(*i);
78+
else
79+
YR.push_back(*i);
80+
}
81+
VecPair<T> delta = ClosestPairPoints(PL, XL, YL);
82+
VecPair<T> tmp = ClosestPairPoints(PR, XR, YR);
83+
if (tmp.Dist() < delta.Dist())
84+
delta = tmp;
85+
std::vector<Vector<T>> YY;
86+
for (auto i = Y.begin(); i != Y.end(); i++) {
87+
T d = i->x - l;
88+
if (d*d < delta.Dist())
89+
YY.push_back(*i);
90+
}
91+
for (size_t i = 0; i < YY.size(); i++)
92+
for (size_t j = i + 1; j <= i + 8 && j < YY.size(); j++) {
93+
VecPair<T> vp(YY[i], YY[j]);
94+
if (vp.Dist() < delta.Dist())
95+
delta = vp;
96+
}
97+
return delta;
98+
}
99+
100+
template <typename T>
101+
VecPair<T> ClosestPairPoints(std::vector<Vector<T>>& Q) {
102+
std::vector<Vector<T>> X(Q), Y(Q);
103+
uset_vec P(Q.begin(), Q.end());
104+
auto fX = [](const Vector<T>& a, const Vector<T>& b){ return a.x < b.x; };
105+
auto fY = [](const Vector<T>& a, const Vector<T>& b){ return a.y < b.y; };
106+
std::sort(X.begin(), X.end(), fX);
107+
std::sort(Y.begin(), Y.end(), fY);
108+
return ClosestPairPoints(P, X, Y);
109+
}
110+
#endif
111+
112+
#ifdef MAIN_ClosestPairPoints
113+
int main(int argc, char *argv[]) {
114+
const size_t n = get_argv(argc, argv, 1, 200);
115+
const size_t m = get_argv(argc, argv, 2, 10);
116+
std::vector<int> b;
117+
random_integers(b, -n, n, m * 2);
118+
using T = double;
119+
std::vector<Vector<T>> Q, S;
120+
Q.reserve(m);
121+
for (size_t i = 0; i < m; i++)
122+
Q.push_back(Vector<T>(b[2 * i + 0], b[2 * i + 1]));
123+
VecPair<T> ans = ClosestPairPoints(Q);
124+
std::cout << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>"
125+
<< std::endl;
126+
std::cout << "<svg height=\"" << 2 * n << "\" width=\"" << 2 * n << "\">"
127+
<< std::endl;
128+
std::cout << "\t<rect fill=\"#ffffff\" x=\"0\" y=\"0\" width=\"" << 2 * n
129+
<< "\" height=\"" << 2 * n << "\"/>" << std::endl;
130+
for (auto i = Q.begin(); i != Q.end(); i++)
131+
std::cout << "\t<circle cx=\"" << n + i->x + 1 << "\" cy=\""
132+
<< n + i->y + 1 << "\" r=\"2\"/>" << std::endl;
133+
print_seg(ans.a, ans.b, (T) n, "#00ff00");
134+
std::cout << "</svg>" << std::endl;
135+
return 0;
136+
}
137+
#endif
138+

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@
221221
| 33 | AnySegmentsIntersect.cpp | Any Segments Intersect | 1025 |
222222
| 33 | GrahamScan.cpp | Graham Scan | 1031 |
223223
| 33 | JarvisMarch.cpp | Jarvis March | 1038 |
224+
| 33 | ClosestPairPoints.cpp | Closest Pair Points | 1043 |
224225

225226
# Supplementary Files
226227
* `utils.h`: Utils

SegmentsIntersect.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ class Vector {
5050
T x, y;
5151
};
5252

53+
template <typename T>
54+
struct VectorHash {
55+
std::size_t operator()(Vector<T> t) const {
56+
size_t a = std::hash<T>()(t.x);
57+
size_t b = std::hash<T>()(t.y);
58+
const size_t shift = sizeof(size_t) * 4;
59+
size_t B = b >> shift | b << shift;
60+
return a ^ B;
61+
}
62+
};
63+
5364
template <typename T>
5465
void print_seg(Vector<T>& p1, Vector<T>& p2, T n, std::string stroke) {
5566
std::cout << "\t<line x1=\"" << n + p1.x + 1 << "\" y1=\"" << n + p1.y + 1

0 commit comments

Comments
 (0)