版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/81530415
题意
给出两个点集,大小分别为 ,然后求出分别两个点集的凸包,问这两个凸包是否全等。
分析
两个凸包全等当且仅当一个凸包在旋转或平移后可以与另一个重合。这样的话他们的角就是一一对应的且边也是一一对应的,那么我们将凸包的边和角组成一个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;
}