CF 474C Captain Marmot

本文介绍了一种通过四重循环暴力枚举所有可能的旋转方式来判断四个点是否能构成正方形的算法,并通过旋转矩阵实现坐标转换。该算法旨在寻找使四个点形成正方形所需的最小旋转次数。

直接四重循环暴力枚举出所有的旋转,判断旋转后的四个点是不是正方形,更新最小值。


#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;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值