First understand the convex hull
To put it bluntly, we must first define the Convex. Simply put, the point on the line segment where any two points in the plane's neighbor are located is in this neighbor, and the neighbor is convex. Simply think about it, we can find that if the first derivative of the neighboring area is not continuous, it cannot be linearly expressed by a point set. The following content is a mathematical analysis, which is not helpful for our algorithm design.
The general computational geometric problem is the plane domain formed by the discrete point set. Therefore, we are interested in finding a convex polygon with the smallest area of the point set. This is the convex bag. As a common sense, we should also know that the vertex on the convex hull must be a subset of the vertex set, so we can design efficient algorithms based on this nature.
The following describes three methods to calculate the convex hull of a plane point set. Pay special attention to the relationship between the convex hull of a polygon and the convex hull of a plane point set.
Gift wrapping method.
Graham-Scan: this should be the oldest O (nlgn) algorithm, and its implementation is relatively simple. Its basic idea is to maintain a convex curve, therefore, it requires the algorithm to know at least one point on the convex hull as its starting point (fortunately, this is relatively simple ). It has a disadvantage that using it directly to find a convex hull of a given polygon may lead to errors (the algorithm art gives the example). Therefore, the algorithm must sort vertices before it starts.
Melkman: The best convex hull algorithm so far. I strongly recommend this algorithm. Its basic operations are the same as those of Graham-scan, except that it obtains the convex hull formed by the current site at any time, therefore, it has an incomparable advantage: it is an online algorithm (you do not have to re-calculate to add a vertex to the vertex set ). Given a polygon, it can directly obtain its convex hull without first ordering. But its biggest advantage is that the implementation is very simple, so it is especially suitable for use in the competition.
Although melkman is good, graham_scan is commonly used.
Sorting of preparation points and Determination of left turn
Point sorting
Some preprocessing processes are usually required for finding convex packets of a fixed point set. The sorting of points is one of them. The following provides a method to sort points by certain rules. This preprocessing process plays an important role in many convex packet search algorithms.
<? XML: namespace prefix = v ns = "urn: Schemas-Microsoft-com: VML"/>
1. Find a point that must be on the convex hull (this is easy to ^ _ ^, usually take the smallest point of the horizontal or vertical coordinates), as P0,
2. link P0 with other points to calculate the angle between these line segments and the vertical downward direction, and place the other end of each line segment (P0 at one end) in the ascending order of the angle) labels: P1, P2, P3 ......
Left turn Determination
This is a classic computational geometric problem, to determine whether the vector p1 = (x1, Y1) to p2 = (X2, Y2) Do left turn, just need to judge X1 * y2-x2 * Y1 positive and negative, if the result is positive, perform left turn from P1 to P2. That is, the cross product of the vector.
The Graham algorithm is like this.
1. Sort all points (see the basics). To ensure the formation of a circle, place P0 at the end of the vertex table;
2. Prepare a stack: Create a stack S, set the stack pointer to T, and press the points 0, 1, and 2 into the stack S;
3. For the next vertex I
As long as s [T-1], s [T], I do not turn left
The stack is reversed;
Push I into Stack s
4. vertices in the stack are the convex packets;
Its core is represented in C language, just the following section:
T =-1;
S [++ T] = 0; s [++ T] = 1; s [++ T] = 2;
For (I = 3; I <n; I ++)
{
While (! Left (s [T-1], s [T], I ))
T --;
S [++ T] = I;
}
Complete code
Int top; // Number of vertices in the convex hull
Struct point
{
Int X, Y;
} P [maxn], stack [maxn];
Int max (int A, int B)
{
Return A> B? A: B;
}
Int DIS (point P1, point P2) // the square of the distance between two points
{
Return (p1.x-p2.x) * (p1.x-p2.x) + (p1.y-p2.y) * (p1.y-p2.y );
}
// Cross product. The result is smaller than the Polar Angle indicating that the vector p0p1 is greater than the Polar Angle of p0p2.
Int multi (point P1, point P2, point P0)
{
Return (p1.x-Snapshot X) * (p2.y-Snapshot y)-(p2.x-Snapshot X) * (p1.y-Snapshot y );
}
Int CMP (point a, point B)
{
If (multi (A, B, P [0])> 0)
Return 1;
If (multi (A, B, P [0]) = 0 & DIS (A, P [0]) <DIS (B, P [0])
Return 1;
Return 0;
}
// The essence of graham_scan
Void graham_scan (point P [], point stack [], int N)
{
Int I, j, k = 0;
Top = 2;
Point temp;
// Find the lowest and leftmost Vertex
For (I = 1; I <n; I ++)
If (P [I]. Y <p [K]. Y | (P [I]. y = P [K]. y) & (P [I]. x <p [K]. X )))
K = I;
// Specify this point as P [0 ];
Temp = P [0];
P [0] = P [k];
P [k] = temp;
// Sort by the polar angle from small to large and the distance is short.
// The above is the essence. If you write the above statement, it may time out, or use the following sort
Sort (p + 1, P + N, CMP );
// Core
Stack [0] = P [0], stack [1] = P [1], stack [2] = P [2];
For (I = 3; I <n; I ++)
{
While (top> 1 & multi (P [I], stack [Top], stack [Top-1])> = 0)
Top --;
Stack [++ top] = P [I];
}
}