NOI 1087

题目:给出1000个点,找其中可以构成正方形的个数

基本想法:枚举边,同时满足长度相等,中心相等,方向垂直即可。

方案一:处理出所有的边,log地查找符合要求的边。复杂度(ElogE),E<5*1e5,T

方案二:枚举对角顶点,每次计算出剩下两个顶点的位置,位置都存在点,则满足条件。复杂度(Elogn),E<5*1e5,n<1e3,T。

方案二T了就很懵逼,5*1e6都能跪??

然后发现我在计算的时候用例atan和sin, cos,当时为了解决这个精度问题还要重写比较函数。

把计算方法改成相似计算就行了。

#include<iostream>
#include<map>
#include<cmath>
#include<cstdio>
using namespace std;

const double INF=1e18+7;

struct Key{
    double x,y;
    Key(){}
    Key(double a,double b){
        x=a;y=b;
    }
    bool operator <(Key a)const{
        if(abs(x-a.x)>1e-6) return x<a.x;
        if(abs(y-a.y)>1e-6) return y<a.y;
        return false;
    }
};

struct Point{
    double x,y;
    Point(){}
    Point(double x,double y){
        this->x=x;
        this->y=y;
    }
    Point operator +(Point a) const{
        return Point(x+a.x,y+a.y);
    }
    Point operator -(Point a) const{
        return Point(x-a.x,y-a.y);
    }
    Point operator *(double k) const{
        return Point(x*k,y*k);
    }
    Point operator /(double k) const{
        return Point(x/k,y/k);
    }
}p[1010];


double dis(int i,int j){
    return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}

int main(){
    int n;
    while(~scanf("%d",&n)&&n){
        map<Key, int> mmm;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&p[i].x,&p[i].y);
            mmm[Key(p[i].x,p[i].y)]++;
        }
        int cnt=0;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                Point a,b;
                Point mid((p[i].x+p[j].x)/2,(p[i].y+p[j].y)/2);
                double dist=dis(i,j);
                if(p[i].x==p[j].x){
                    a=Point(mid.x+dist/2.0,mid.y);
                    b=Point(mid.x-dist/2.0,mid.y);
                }
                else if(p[i].y==p[j].y){
                    a=Point(mid.x,mid.y+dist/2.0);
                    b=Point(mid.x,mid.y-dist/2.0);
                }
                else{
                    double changex=abs(p[i].x-mid.x);
                    double changey=abs(p[i].y-mid.y);
                    double k=(p[i].y-p[j].y)/(p[i].x-p[j].x);
                    if(k>0){
                        a=Point(mid.x+changey,mid.y-changex);
                        b=Point(mid.x-changey,mid.y+changex);
                    }
                    else{
                        a=Point(mid.x+changey,mid.y+changex);
                        b=Point(mid.x-changey,mid.y-changex);
                    }
                }
                if(mmm[Key(a.x,a.y)]&&mmm[Key(b.x,b.y)]) cnt++;
            }
        }
        cout<<cnt/2<<endl;
    }
}



猜你喜欢

转载自blog.csdn.net/mengwuyaaa/article/details/80744080
今日推荐