Codeforces Round #502 (Div. 1 + Div. 2) E. The Supersonic Rocket(计算几何+KMP)

版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/81530415

题意

  给出两个点集,大小分别为 n , m ,然后求出分别两个点集的凸包,问这两个凸包是否全等。

分析

  两个凸包全等当且仅当一个凸包在旋转或平移后可以与另一个重合。这样的话他们的角就是一一对应的且边也是一一对应的,那么我们将凸包的边和角组成一个pair,将其中一个凸包的pair延长一倍,用另一个pair用KMP在这上面匹配,如果在某个地方可以匹配上,两个凸包就是全等的。(然而我写翔了,忘了可以用pair来进行KMP,于是对着边和角分别进行了一次KMP。虽然也可以过233)

Code

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-6,pi=acos(-1.0);
inline int dcmp(double x) {
    if(fabs(x)<eps)
        return 0;
    return x<0?-1:1;
}
inline double sqr(double x) {
    return x*x;
}
struct Point {
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){};
    inline void in() {
        scanf("%lf%lf",&x,&y);
    }
};
inline Point operator - (Point A,Point B) {
    return Point(A.x-B.x,A.y-B.y);
}
inline Point operator * (Point A,double p) {
    return Point(A.x*p,A.y*p);
}
inline bool operator < (const Point &a,const Point &b) {
    return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
inline double Dot(Point A,Point B) {
    return A.x*B.x+A.y*B.y;
}
inline double Length(Point A) {
    return sqrt(Dot(A,A));
}
inline double GetAngle(Point A,Point B) {
    return acos(Dot(A,B)/Length(A)/Length(B));
}
inline double Cross(Point A,Point B) {
    return A.x*B.y-A.y*B.x;
}
inline int ConvexHull(Point *p,int n,Point *ans) {
    sort(p,p+n);
    int m=0;
    for(int i=0;i<n;i++) {
        while(m>1&&Cross(ans[m-1]-ans[m-2],p[i]-ans[m-2])<=0)
            m--;
        ans[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;~i;i--) {
        while(m>k&&Cross(ans[m-1]-ans[m-2],p[i]-ans[m-2])<=0)
            m--;
        ans[m++]=p[i];
    }
    if(n>1)
        m--;
    return m;
}
typedef long long ll;
inline ll distan(Point p,Point q) {
    return (p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y);
}
Point p[100005],q[100005],cp[200005],cq[200005];
int n,m,lx,ly,fail[100005];
ll dp[100005],dq[200005];
double ap[100005],aq[200005];
bool vis[100005];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)
        p[i].in();
    for(int i=0;i<m;++i)
        q[i].in();
    lx=ConvexHull(p,n,cp);
    ly=ConvexHull(q,m,cq);
    if(lx!=ly)
        return 0*puts("NO");
    cp[lx]=cp[0],lx++;
    cp[lx]=cp[1];
    for(int i=0;i<ly;++i)
        cq[i+ly]=cq[i];
    ly<<=1;
    cq[ly]=cq[0],ly++;
    cq[ly]=cq[1];
    for(int i=1;i<lx;++i)
        dp[i]=distan(cp[i],cp[i-1]);
    for(int i=1;i<ly;++i)
        dq[i]=distan(cq[i],cq[i-1]);
    for(int i=1;i<lx;++i)
        ap[i]=GetAngle(cp[i-1]-cp[i],cp[i+1]-cp[i]);
    for(int i=1;i<ly;++i)
        aq[i]=GetAngle(cq[i-1]-cq[i],cq[i+1]-cq[i]);
    fail[1]=0;
    int j=0;
    for(int i=2;i<lx;++i) {
        while(j&&dp[i]!=dp[j+1])
            j=fail[j];
        if(dp[i]==dp[j+1])
            j++;
        fail[i]=j;
    }
    j=0;
    for(int i=1;i<ly;++i) {
        while(j&&dq[i]!=dp[j+1])
            j=fail[j];
        if(dq[i]==dp[j+1])
            j++;
        if(j==lx-1)
            vis[i]=1;
    }
    fail[1]=0;
    j=0;
    for(int i=2;i<lx;++i) {
        while(j&&dcmp(ap[i]-ap[j+1]))
            j=fail[j];
        if(!dcmp(ap[i]-ap[j+1]))
            j++;
        fail[i]=j;
    }
    j=0;
    for(int i=1;i<ly;++i) {
        while(j&&dcmp(aq[i]-ap[j+1]))
            j=fail[j];
        if(!dcmp(aq[i]-ap[j+1]))
            j++;
        if(j==lx-1)
            if(vis[i])
                return 0*puts("YES");
    }
    puts("NO");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Effervescence/article/details/81530415