Introduction to Rotation Jams + Template Questions (POJ 2187)

The first contact with the rotation stuck (should read xuán zhuǎn qiǎ ké) was a question on CSU (this question has no A so far, and I don’t know if it is a metaphysical operation), but this is not important, the important thing is to learn new knowledge!

some history

The 1978 paper "Computational Geometry" by MI Shamos's Ph.D. marked the birth of this field of computer science. What he published at the time was a very simple algorithm for finding the diameter of a convex polygon, which was determined according to the maximum distance between a pair of points in the polygon.
Later the diameter evolved to be determined by a pair of opposite points. Shamos presents a simple O(n) time algorithm to determine the pair of opposites of a convex n-gon. Since they have at most 3n/2 pairs, the diameter can be calculated in O(n) time.
As Toussaint later proposed, Shamos's algorithm is like rotating a pair of jams around a polygon. Hence the term "rotary jam". In 1983, Toussaint published a paper in which the same technique was used to solve many problems. Since then, new algorithms based on this model have been established, solving many problems.
They include:
Calculated Distance
Convex Polygon Diameter
Convex Polygon Width
Maximum Distance Between
Convex Polygons Minimum Distance Between Convex Polygons
Circumscribed Rectangle
Minimum Area Circumscribed Rectangle
Minimum Perimeter Circumscribed Rectangle
Triangulation
Onion Triangulation
Spiral Triangulation
Quadrilateral
Convex Polygon Properties
Merge Convex Hull
Find Common Tangent
Convex Polygon Intersection
Critical Tangent
Convex Polygon Vector
Sum Thinnest
Section Thinnest Cross Section


Then I will talk about the idea of ​​the rotating jam algorithm: key content

In simple terms, the convex hull is "stuck" with a pair of parallel lines for rotation.

The corresponding point that is just stuck by a pair of stuck shells is called the opposite point (as shown in the figure below),
write picture description here
it can be proved that the number of the opposite point does not exceed 3N/2, that is to say, the number of
the The number of points is also the guarantee of the time complexity of our problem solving below

There are two cases of jamming:
one, two parallel lines are stuck with exactly two points,
write picture description here
two , one side and one point are stuck respectively.
write picture description here
In the second case, we can see the distance ratio between an opposite point and the corresponding side. The distance from other points to that side should be larger
, that is, the area of ​​the triangle formed by an antipodal point and the corresponding side is the largest. Next, we will get the simplified method of finding the antipodal point accordingly.

The upper vertex of the yellow triangle is the opposite point of the base.

According to the second case above, we can get the following method:
write picture description here
If qa and qb are the two farthest points on the convex hull, we can definitely draw a pair of parallel lines through qa and qb respectively. By rotating this pair of parallel lines, we can make it coincide with an edge on the convex hull, as shown in the blue line in the figure, you can notice that qa is the point on the convex hull that is farthest from the line where p and qb are located. So our idea is to enumerate all the edges on the convex hull, find the vertex farthest from the edge on the convex hull for each edge, calculate the distance from this vertex to the two endpoints of the edge, and record the largest value.

Intuitively, this is an O(n2) algorithm, the same as enumerating any two vertices directly.

However, we can find that the distance between the points on the convex hull and the corresponding edge is a unimodal function (as shown in the figure below),
write picture description here
which is very important.

According to the characteristics of this convex hull, we noticed that when enumerating the edges counterclockwise, the change of the farthest point is also counterclockwise, so that the calculation of the farthest point can be continued without recalculating the farthest point from the beginning. . So we get an O(n) algorithm. It's called "spinning" it!
Using the rotating card shell, we can get the longest length point pair in the convex hull's pair of points in O(n) time.
And since the farthest point pair must belong to the set of opposite point pairs, then we first find the convex hull, then find the set of opposite point pairs, and then select the one with the largest distance.
Then the specific code is easy to implement, using the cross product.

Learning is about to strike while the iron is hot
. A template question: POJ 2187 Beauty Contes

The AC codes are as follows:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;

const int MAXN=50000+7;

struct Points{
    int x,y;
    Points(int x=0,int y=0):x(x),y(y){}
};

typedef Points Vector;
Vector operator -(Points A,Points B){
    return Vector(A.x-B.x,A.y-B.y);
}
int n,m,maxdis;
Points p[MAXN],ch[MAXN];

int Cross(Vector A,Vector B){
    return A.x*B.y-A.y*B.x;
}

bool cmp(Points a,Points b){
    bool ret=false;
    if(a.x<b.x||(a.x==b.x&&a.y<b.y)) ret=true;
    return ret;
}
void ConvexHull(){
    sort(p,p+n,cmp);
    m=0;
    for(int i=0;i<n;++i){
        while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;--i){
        while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    if(n>1) m--;
} 

int dis(Points a,Points b){
    return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y);
}
void rotating_caliper(){
    if(n==3){
        maxdis=max(dis(p[0],p[1]),dis(p[0],p[2]));
        maxdis=max(maxdis,dis(p[1],p[2]));
    }else{
        int j=2;
        for(int i=0;i<m;++i){
            while(abs(Cross(ch[i]-ch[i+1],ch[j]-ch[i+1]))<abs(Cross(ch[i]-ch[i+1],ch[j+1]-ch[i+1]))){
                j=(j+1)%m;
            }
            maxdis=max(maxdis,dis(ch[i],ch[j]));
        }
    }
}

int main(){
    cin>>n;
    for(int i=0;i<n;++i){
        cin>>p[i].x>>p[i].y;
    }
    maxdis=-1;
    if(n==2){
        maxdis=dis(p[0],p[1]);
    }else{
        ConvexHull();
        rotating_caliper();
    }
    cout<<maxdis;
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325742898&siteId=291194637