题目大意
给出两个点集,判断能否对其中一个点集进行旋转、平移、翻转、放大后与另一个重合。
扯淡
第一眼看上去似乎很难
看题解看到懵逼,别人的方法感觉不太可靠
于是随手写下自己的方法发现跑得挺快
咳咳
正题
先不看题目。
假设有两张纸片,要判断这两张纸片是否相似,怎么做?
判断相似,肯定要先把它们放在一起。
至于怎么放在一起,如果实际操作,只需大致找一个点。
但是在程序中无法随便找一个点,所以直接找它们的重心。
重心有一个性质,只要两个图形相似,那么它们重心的相对位置相同。
重心的求法:
重心(x,y)
x=(Σx[i])/n
y=(Σy[i])/n
其实就是x与y的平均值。
然后把两个点集分别以重心为原点,建立新的坐标系。
接下来,如何判断两个图形相似?
在现实中,其实可以旋转其中一个,然后看两个图形的边缘是否相同。
但是如果我们这样做的话,时间将是平方级。
想想可以直到,如果两个图形相似,那么它们的点与原点的连边一定成相同的比例。
那么一个点集中的最远点,在另一个点集中一定相对应。
所以可以求出一个点集与另一个的比例,然后从两个最远点开始,判断两个点集是否相同。
如果两个点集都有多个最远点,那么从其中一个的一个最远点开始,和另一个点集的所有最远点相匹配。
因为所有点都是整点,所以25000以内的最远点个数不超20个。
code
350+行。。。
其实翻转前后基本一样,两个快拍可以自带,某些细节可以优化
最简应该100行左右吧。。
#include <iostream>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define error 0.000001
using namespace std;
long double x[25001];
long double y[25001];
long double ang[25001];
long double len[25001];
long double X[25001];
long double Y[25001];
long double Ang[25001];
long double Len[25001];
int n,i,j,k,l,m,Q,ls;
long double avex,avey,maxlen,maxlen_ang,Avex,Avey,Maxlen,Maxlen_ang,s,ang1,ang2;
bool bz;
void qsort(int l,int r)
{
int i,j,k;
long double mid,Mid;
i=l;
j=r;
mid=ang[(l+r)/2];
Mid=len[(l+r)/2];
while (i<=j)
{
while ((ang[i]<mid) || ((ang[i]==mid) && (len[i]<Mid))) i++;
while ((ang[j]>mid) || ((ang[j]==mid) && (len[j]>Mid))) j--;
if (i<=j)
{
ang[0]=ang[i];
ang[i]=ang[j];
ang[j]=ang[0];
len[0]=len[i];
len[i]=len[j];
len[j]=len[0];
i++;
j--;
}
}
if (l<j)
qsort(l,j);
if (i<r)
qsort(i,r);
return;
}
void Qsort(int l,int r)
{
int i,j,k;
long double mid,Mid;
i=l;
j=r;
mid=Ang[(l+r)/2];
Mid=Len[(l+r)/2];
while (i<=j)
{
while ((Ang[i]<mid) || ((Ang[i]==mid) && (Len[i]<Mid))) i++;
while ((Ang[j]>mid) || ((Ang[j]==mid) && (Len[j]>Mid))) j--;
if (i<=j)
{
Ang[0]=Ang[i];
Ang[i]=Ang[j];
Ang[j]=Ang[0];
Len[0]=Len[i];
Len[i]=Len[j];
Len[j]=Len[0];
i++;
j--;
}
}
if (l<j)
Qsort(l,j);
if (i<r)
Qsort(i,r);
return;
}
int main()
{
scanf("%d",&n);
fo(i,1,n)
scanf("%Lf%Lf",&x[i],&y[i]),avex+=x[i],avey+=y[i];
avex/=n,avey/=n;
fo(i,1,n)
{
x[i]-=avex;
y[i]-=avey;
len[i]=sqrt(x[i]*x[i]+y[i]*y[i]);
if ((x[i]==0) && (y[i]>0))
ang[i]=90;
else
if ((x[i]==0) && (y[i]<0))
ang[i]=270;
else
if ((x[i]>0) && (y[i]==0))
ang[i]=0;
else
if ((x[i]<0) && (y[i]==0))
ang[i]=180;
else
if ((x[i]==0) && (y[i]==0))
ang[i]=-1;
else
{
ang[i]=180*atan(y[i]/x[i])/M_PI;
if ((x[i]<0) && (y[i]>0))
ang[i]+=180;
else
if ((x[i]<0) && (y[i]<0))
ang[i]+=180;
else
if ((x[i]>0) && (y[i]<0))
ang[i]+=360;
}
}
j=0;
maxlen=0;
fo(i,1,n)
if (len[i]>maxlen)
{
maxlen=len[i];
j=i;
}
maxlen_ang=ang[j];
fo(i,1,n)
if (ang[i]>=0)
{
ang[i]=ang[i]-maxlen_ang;
if (ang[i]<0)
ang[i]+=360;
}
qsort(1,n);
if (ang[1]<0)
ang[1]=0;
scanf("%d",&Q);
for (;Q;Q--)
{
Avex=0;
Avey=0;
scanf("%d",&j);
fo(i,1,j)
scanf("%Lf%Lf",&X[i],&Y[i]),Avex+=X[i],Avey+=Y[i];
if (j!=n)
{
printf("No\n");
continue;
}
Avex/=n,Avey/=n;
fo(i,1,n)
{
X[i]-=Avex;
Y[i]-=Avey;
Len[i]=sqrt(X[i]*X[i]+Y[i]*Y[i]);
if ((X[i]==0) && (Y[i]>0))
Ang[i]=90;
else
if ((X[i]==0) && (Y[i]<0))
Ang[i]=270;
else
if ((X[i]>0) && (Y[i]==0))
Ang[i]=0;
else
if ((X[i]<0) && (Y[i]==0))
Ang[i]=180;
else
if ((X[i]==0) && (Y[i]==0))
Ang[i]=-1;
else
{
Ang[i]=180*atan(Y[i]/X[i])/M_PI;
if ((X[i]<0) && (Y[i]>0))
Ang[i]+=180;
else
if ((X[i]<0) && (Y[i]<0))
Ang[i]+=180;
else
if ((X[i]>0) && (Y[i]<0))
Ang[i]+=360;
}
}
j=0;
Maxlen=0;
fo(i,1,n)
if (Len[i]>Maxlen)
{
Maxlen=Len[i];
j=i;
}
Maxlen_ang=Ang[j];
fo(i,1,n)
if (Ang[i]>=0)
{
Ang[i]=Ang[i]-Maxlen_ang;
if (Ang[i]<0)
Ang[i]+=360;
}
Qsort(1,n);
if (Ang[1]<0)
Ang[1]=0;
if (maxlen)
{
s=Maxlen/maxlen;
fo(i,1,n)
Len[i]/=s;
}
fo(i,1,n)
if (len[1]==Len[i])
{
bz=1;
k=i;
ang2=0;
fo(j,2,n)
{
ls=k;
k=k%n+1;
ang2+=(Ang[k]>=Ang[ls])?(Ang[k]-Ang[ls]):((360-Ang[ls])+Ang[k]);
if (((abs(len[j]-Len[k]))>error) || ((abs(ang[j]-ang2))>error))
{
bz=0;
break;
}
}
if (bz)
break;
}
if (bz)
{
printf("Yes\n");
continue;
}
fo(i,1,n)
{
X[i]=-X[i];
Y[i]=Y[i];
Len[i]=sqrt(X[i]*X[i]+Y[i]*Y[i]);
if ((X[i]==0) && (Y[i]>0))
Ang[i]=90;
else
if ((X[i]==0) && (Y[i]<0))
Ang[i]=270;
else
if ((X[i]>0) && (Y[i]==0))
Ang[i]=0;
else
if ((X[i]<0) && (Y[i]==0))
Ang[i]=180;
else
if ((X[i]==0) && (Y[i]==0))
Ang[i]=-1;
else
{
Ang[i]=180*atan(Y[i]/X[i])/M_PI;
if ((X[i]<0) && (Y[i]>0))
Ang[i]+=180;
else
if ((X[i]<0) && (Y[i]<0))
Ang[i]+=180;
else
if ((X[i]>0) && (Y[i]<0))
Ang[i]+=360;
}
}
j=0;
Maxlen=0;
fo(i,1,n)
if (Len[i]>Maxlen)
{
Maxlen=Len[i];
j=i;
}
Maxlen_ang=Ang[j];
fo(i,1,n)
if (Ang[i]>=0)
{
Ang[i]=Ang[i]-Maxlen_ang;
if (Ang[i]<0)
Ang[i]+=360;
}
Qsort(1,n);
if (Ang[1]<0)
Ang[1]=0;
if (maxlen)
{
s=Maxlen/maxlen;
fo(i,1,n)
Len[i]/=s;
}
fo(i,1,n)
if (len[1]==Len[i])
{
bz=1;
k=i;
ang2=0;
fo(j,2,n)
{
ls=k;
k=k%n+1;
ang2+=(Ang[k]>=Ang[ls])?(Ang[k]-Ang[ls]):((360-Ang[ls])+Ang[k]);
if (((abs(len[j]-Len[k]))>error) || ((abs(ang[j]-ang2))>error))
{
bz=0;
break;
}
}
if (bz)
break;
}
if (bz)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}