Convex hull, the nearest point, and a half-plane rotation stuck post

It is four more important computational geometry knowledge of it, write here a note.

PS: This article default reader to understand the most basic knowledge of computational geometry, it does not provide any template.


Convex hull:

The convex hull concept: Given $ n (n≥3) $ points, can find these points contains the minimum area including the polygon.

Generally, we use Andrew convex hull algorithm, time complexity is $ O (nlogn) $.

Andrew idea of ​​the algorithm is very simple to do positive and negative scans were under construction on the convex hull and convex hull.

Considering the structure of the convex hull of the process, we maintain a stack, assuming that we now have three points $ p_1, p_2, p_3 $, now found $ p_4p_3 $ for $ p_3p_2 $ is a right bend, it means $ p_3 $ is not convex the package, then the $ $ P_3 the stack, continue to check for $ $ P_2.

The convex hull configuration is the same reason, each time point out of the stack up, so is the complexity of the scanned $ O (n) $, since we have once for all points in ascending order ($ X $ coordinates of a first key word, $ $ Y coordinates of a second key), so the overall complexity is $ O (nlogn) $.

Template question: Luogu P2742

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const double EPS = 1e-8;
 5 const int MAXN = 10010;
 6 
 7 struct Point
 8 {
 9     double x, y;
10     Point(double X = 0.0, double Y = 0.0){x = X, y = Y;}
11     Point operator + (Point B) {return Point(x + B.x, y + B.y);}
12     Point operator - (Point B) {return Point(x - B.x, y - B.y);}
13     bool operator == (Point B) {return fabs(x - B.x) < EPS && fabs(y - B.y) < EPS;}
14 };
15 typedef Point Vector;
16 inline double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}
17 inline double Dis(Point A, Point B) {return hypot(A.x - B.x, A.y - B.y);}
18 inline bool cmp(const Point &A, const Point &B) {return fabs(A.x - B.x) < EPS ? A.y - B.y < EPS : A.x - B.x < EPS;}
19 
20 int n, cnt; double res;
21 Point p[MAXN], ans[MAXN];
22 
23 void Convex()
24 {
25     sort(p + 1, p + 1 + n, cmp);
26     n = unique(p + 1, p + 1 + n) - p - 1;
27     for(int i = 1; i <= n; ++i)
28     {
29         while(cnt > 1 && Cross(ans[cnt] - ans[cnt - 1], p[i] - ans[cnt - 1]) < EPS) --cnt;
30         ans[++cnt] = p[i];
31     }
32     int j = cnt;
33     for(int i = n - 1; i; --i)
34     {
35         while(cnt > j && Cross(ans[cnt] - ans[cnt - 1], p[i] - ans[cnt - 1]) < EPS) --cnt;
36         ans[++cnt] = p[i];
37     }
38     if(n > 1) --cnt;
39 }
40 
41 int main()
42 {
43     while(scanf("%d", &n) != EOF && n)
44     {
45         for(int i = 1; i <= n; ++i) scanf("%lf %lf", &p[i].x, &p[i].y);
46         cnt = 0, res = 0.0; Convex();
47         if(cnt == 2) res = Dis(ans[1 ] years [ 2 ]);
48          else  if (cnt> = 3 )
 49          {
 50              res = Dis (years [cnt], years [ 1 ]);
51              for ( int i = 1 ; i <cnt; ++ i) res + = Dis (years [i] years [i + 1 ]);
52          }
 53          printf ( " % .2f \ n " , res);
54      }
 55      return  0 ;
56 }

Closest point:

Violence is $ O (n ^ 2) $ in consideration partition (partition prior to sorting, sort by reference to convex hull algorithm).

When the current interval is only a point or two points, the distance can be calculated directly.

The question now is how to merge the two intervals, hypothesis two intervals were $ S_1, S_2 $.

Make $ S_1, the closest distance S_2 $ are, respectively, $ d_1, d_2 $.

Then we at an intermediate point $ p [mid] $ find all less than the distance from which $ min (d_1, d_2) $ a point near, so that these set points to $ tmp $.

Then we follow the $ y $ coordinates for $ tmp $ sort of point, point after violent enumerate $ tmp $ in, pruning and use $ y $ coordinate monotony.

Can demonstrate that such complexity is $ O (nlogn) $ a.

Template question: Luogu P1429

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int MAXN = 200010;
 5 const double EPS = 1e-8;
 6 
 7 struct Point
 8 {
 9     double x, y;
10 };
11 inline double Dis(Point A, Point B) {return hypot(A.x - B.x, A.y - B.y);}
12 inline bool cmp1(Point A, Point B) {return fabs(A.x - B.x) < EPS ? A.y - B.y < EPS : A.x - B.x < EPS;}
13 inline bool cmp2(Point A, Point B) {return A.y - B.y < EPS;}
14 
15 int n;
16 Point p[MAXN], tmp[MAXN];
17 
18 double solve(int l, int r)
19 {
20     double dis = 1e20;
21     if(l == r) return dis;
22     if(l + 1 == r) return Dis(p[l], p[r]);
23     int mid = (l + r) >> 1;
24     double d1 = solve(l, mid);
25     double d2 = solve(mid + 1, r);
26     dis = min(d1, d2);
27     int cnt = 0;
28     for(int i = l; i <= r; ++i)
29         if(fabs(p[mid].x - p[i].x) <= dis)
30             tmp[++cnt] = p[i];
31     sort(tmp + 1, tmp + 1 + cnt, cmp2);
32     for(int i = 1; i <= cnt; ++i)
33         for(int j = i + 1; j <= cnt; ++j)
34         {
35             if(tmp[j].y - tmp[i].y >= dis) break;
36             dis = min(dis, Dis(tmp[j], tmp[i]));
37         }
38     return dis;
39 }
40 
41 int main()
42 {
43     scanf("%d", &n);
44     for(int i = 1; i <= n; ++i) scanf("%lf %lf", &p[i].x, &p[i].y);
45     sort(p + 1, p + 1 + n, cmp1);
46     printf("%.4f\n", solve(1, n));
47     return 0;
48 }

Rotating stuck:

First you have to be convex hull.

Then consider a problem, the plane farthest point right.

First, the farthest point of the convex hull is definitely on, so first find the convex hull.

We call the intersection of two parallel lines of the convex hull of the points for the heel can be shown the number of points of the heel is $ O (n) $ a.

According to the FIG., Readily found to have a particular nature of the heel point.

In short, this is the area of ​​the triangle is a change in the nature of the unimodal function.

Then we counterclockwise enumeration of each point, compute the point of heel point, as long as we can and then on to enumerate counterclockwise heel point one point.

I found that this is equivalent to two parallel lines is the convex hull of the card housing in a circle counterclockwise, the source of which is the name of the algorithm.

Template question: POJ 2187

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<set>
 8 using namespace std;
 9 
10 const int MAXN = 50010;
11 
12 struct Point
13 {
14     int x, y;
15     Point(int X = 0, int Y = 0){x = X, y = Y;}
16     Point operator + (Point B) {return Point(x + B.x, y + B.y);}
17     Point operator - (Point B) {return Point(x - B.x, y - B.y);}
18 };
19 inline bool cmp(const Point &A, const Point &B) {return A.x == B.x ? A.y < B.y : A.x < B.x;}
20 inline int dis(Point A, Point B) {return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y);}
21 inline int Cross(Point A, Point B) {return A.x * B.y - A.y * B.x;}
22 
23 int n, m, ans;
24 Point p[MAXN], q[MAXN];
25 
26 void Convex_hull()
27 {
28     sort(p, p + n, cmp);
29     for(int i = 0; i < n; ++i)
30     {
31         while(m > 1 && Cross(q[m - 1] - q[m - 2], p[i] - q[m - 1]) <= 0) --m;
32         q[m++] = p[i];
33     }
34     for(int i = n - 2, j = m; ~i; --i)
35     {
36         while(m > j && Cross(q[m - 1] - q[m - 2], p[i] - q[m - 1]) <= 0) --m;
37         q[m++] = p[i];
38     }
39     if(n > 1) --m;
40 }
41 
42 int solve()
43 {
44     if(m == 2) return dis(q[0], q[1]);
45     for(int i = 0, j = 1; i < m; ++i)
46     {
47         while(abs(Cross(q[(i + 1) % m] - q[i], q[j] - q[i])) <
48               abs(Cross(q[(i + 1) % m] - q[i], q[(j + 1) % m] - q[i]))) j = (j + 1) % m;
49         ans = max(ans, dis(q[i], q[j]));
50     }
51     return ans;
52 }
53 
54 int main()
55 {
56     scanf("%d", &n);
57     for(int i = 0; i < n; ++i) scanf("%d %d", &p[i].x, &p[i].y);
58     Convex_hull(); printf("%d\n", solve());
59     return 0;
60 }

Half plane cross:

High school mathematics compulsory 5?

We have represented with a straight line to a half-plane (the line is the left half-plane)

For convenience, we may add a few human half-plane, in order to avoid cross-plane is not the last half closed.

Given below is a complex of $ O (nlogn) $ half-plane of the algorithm.

  1. Sort by all half-plane polar angle.
  2. The addition of the first half-plane in the deque.
  3. Individually added half-plane, and three cases are processed.
  • Case 1: If the intersection of the two half-planes of the end of the team out of the current half-plane, then delete the tail half-plane.
  • Case 2: If the intersection of two half-planes of the first team outside of the current half-plane, then delete the team's first half-plane.
  • Case 3: If the intersection of two half-planes of the end of the first half the team out of the plane of the team, then delete the tail half-plane.
  • If you encounter the same polar angle two and a half plane, then we should keep that one on the left.

Template question: Luogu P4196

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int MAXN = 510;
 5 const double EPS = 1e-8;
 6 inline int sgn(double x) {return fabs(x) < EPS ? 0 : (x > 0 ? 1 : -1);}
 7 
 8 struct Point
 9 {
10     double x, y;
11     Point operator + (Point B) {return (Point){x + B.x, y + B.y};}
12     Point operator - (Point B) {return (Point){x - B.x, y - B.y};}
13     Point operator * (double k) {return (Point){x * k, y * k};}
14     Point operator / (double k) {return (Point){x / k, y / k};}
15 };
16 typedef Point Vector;
17 inline double Cross(Point A, Point B) {return A.x * B.y - A.y * B.x;}
18 
19 struct Line
20 {
21     Point p, v;
22     double ang;
23 };
24 inline bool cmp(Line A, Line B) {return sgn(A.ang - B.ang) == 0 ? sgn(Cross(A.v - A.p, B.v - A.p)) > 0 : sgn(A.ang - B.ang) < 0;}
25 
26 Point Cross_point(Line A, Line B)
27 {
28     Vector v1 = A.v - A.p, v2 = B.v - B.p, u = B.p - A.p;
29     double t = Cross(u, v1) / Cross(v1, v2);
30     return B.p + v2 * t;
31 }
32 
33 inline bool OnRight(Line A, Line B, Line C)
34 {
35     Point p = Cross_point(A, B);
36     return sgn(Cross(C.v - C.p, p - C.p)) < 0;
37 }
38 
39 Line a[MAXN], q[MAXN];
40 Point b[MAXN];
41 int n, tot, cnt;
42 
43 void HPI()
44 {
45     sort(a + 1, a + 1 + tot, cmp);
46     for(int i = 1; i <= tot; ++i)
47     {
48         if(sgn(a[i].ang - a[i - 1].ang) != 0) ++cnt;
49         a[cnt] = a[i];
50     }
51     int l = 1, r = 0;
52     q[++r] = a[1], q[++r] = a[2];
53     for(int i = 3; i <= cnt; ++i)
54     {
55         while(l < r && OnRight(q[r - 1], q[r], a[i])) --r;
56         while(l < r && OnRight(q[l + 1], q[l], a[i])) ++l;
57         q[++r] = a[i];
58     }
59     while(l < r && OnRight(q[r - 1], q[r], q[l])) --r;
60     while(l < r && OnRight(q[l + 1], q[l], q[r])) ++l;
61     q[r + 1] = q[l]; tot = 0;
62     for(int i = l; i <= r; ++i) b[++tot] = Cross_point(q[i], q[i + 1]);
63 }
64 
65 int main()
66 {
67     scanf("%d", &n);
68     for(int i = 1; i <= n; ++i)
69     {
70         int k; scanf("%d", &k);
71         for(int j = 1; j <= k; ++j) scanf("%lf %lf", &b[j].x, &b[j].y);
72         b[k + 1] = b[1];
73         for(int j = 1; j <= k; ++j) a[++tot].p = b[j], a[tot].v = b[j + 1];
74     }
75     for(int i = 1; i <= tot; ++i) a[i].ang = atan2(a[i].v.y - a[i].p.y, a[i].v.x - a[i].p.x);
76     HPI(); b[tot + 1] = b[1]; double ans = 0.0;
77     if(tot > 2) for(int i = 1; i <= tot; ++i) ans += Cross(b[i], b[i + 1]);
78     printf("%.3f\n", fabs(ans) / 2.0);
79     return 0;
80 }

 

Guess you like

Origin www.cnblogs.com/Aegir/p/11311843.html