直接四重循环暴力枚举出所有的旋转,判断旋转后的四个点是不是正方形,更新最小值。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define e 1e-8
using namespace std;
void rot(int x,int y,double &x1,double &y1,int a,int b,double angle)
{
x-=a;
y-=b;
x1=x*cos(angle)-y*sin(angle);
y1=x*sin(angle)+y*cos(angle);
x1+=a;
y1+=b;
}
double pi=2.0*acos(0.0);
bool check(double *x,double *y)
{
int i,j;
double dis[5];
dis[2]=sqrt( (x[2]-x[1])*(x[2]-x[1]) + (y[2]-y[1])*(y[2]-y[1]) );
for(j=3;j<=4;j++){
dis[j]=sqrt( (x[j]-x[1])*(x[j]-x[1]) + (y[j]-y[1])*(y[j]-y[1]) );
if(fabs(dis[j]-dis[2])> e){
if(dis[2]<dis[j]){
if( fabs(sqrt(2.0)*dis[2]-dis[j]) > e ) return 0;
}
else{
if( fabs(sqrt(2.0)*dis[j]-dis[2]) > e ) return 0;
}
}
}
double mn=999999999,tmpx[5],tmpy[5];
int ct=0;
for(i=2;i<=4;i++){
mn=min(mn,dis[i]);
}
for(i=2;i<=4;i++){
if( fabs(dis[i]-mn)<e ){
tmpx[ct]=x[i]-x[1];
tmpy[ct++]=y[i]-y[1];
}
}
if(ct!=2) return 0;
return fabs(tmpx[0]*tmpx[1]+tmpy[0]*tmpy[1]-0)<e;
}
int main()
{
int n,i,x[5],y[5],a[5],b[5],j,k,l,m;
double x1[5],y1[5];
scanf("%d",&n);
for(i=1;i<=n;i++){
for(j=1;j<=4;j++){
scanf("%d%d%d%d",&x[j],&y[j],&a[j],&b[j]);
}
int mn=999999999;
for(j=0;j<4;j++){
rot(x[1],y[1],x1[1],y1[1],a[1],b[1],j*pi/2);
for(k=0;k<4;k++){
rot(x[2],y[2],x1[2],y1[2],a[2],b[2],k*pi/2);
for(l=0;l<4;l++){
rot(x[3],y[3],x1[3],y1[3],a[3],b[3],l*pi/2);
for(m=0;m<4;m++){
rot(x[4],y[4],x1[4],y1[4],a[4],b[4],m*pi/2);
if(check(x1,y1)) mn=min(mn,j+k+l+m);
}
}
}
}
if(mn==999999999) printf("-1\n");
else printf("%d\n",mn);
}
return 0;
}
本文介绍了一种通过四重循环暴力枚举所有可能的旋转方式来判断四个点是否能构成正方形的算法,并通过旋转矩阵实现坐标转换。该算法旨在寻找使四个点形成正方形所需的最小旋转次数。
807

被折叠的 条评论
为什么被折叠?



