POJ 2002 统计正方形 HASH

 

题目链接:http://poj.org/problem?id=2002

题意:给定n个点,问有多少种方法可以组成正方形。

思路:我们可以根据两个点求出对应正方形[有2个一个在两点左边,一个在两点右边]另外两个点的左边。例如

已知:(x1,y1) (x2,y2)
则x3=x1+(y1-y2) y3= y1-(x1-x2) x4=x2+(y1-y2) y4= y2-(x1-x2)
或x3=x1-(y1-y2) y3= y1+(x1-x2) x4=x2-(y1-y2) y4= y2+(x1-x2)

枚举两个点,进行HASH,然后再枚举两个点然后求另外两个点,再从HASH表找,冲突用拉链法。

这种做法会使同一个正方形按照不同的顺序被枚举了四次,因此最后的结果要除以4.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
typedef long long int LL;
typedef unsigned int uint;
const int MAXN=1000+5;
const int MOD=99991;
struct Point{
    int x,y;
    Point(int a=0,int b=0):x(a),y(b){};
};
Point P[MAXN];
vector<Point>Hash[MOD];
void Init(){
    for(int i=0;i<MOD;i++){
        Hash[i].clear();
    }
}
void InsetHash(Point a){
    int Num=(a.x*a.x+a.y*a.y)%MOD;
    Hash[Num].push_back(a);
}
bool Search(Point a){
    int Num=(a.x*a.x+a.y*a.y)%MOD;
    for(int i=0;i<Hash[Num].size();i++){
        if(a.x==Hash[Num][i].x&&a.y==Hash[Num][i].y){
            return true;
        }
    }
    return false;
}
int main(){
#ifdef kirito
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    int n;
    while(scanf("%d",&n)&&n){
        int ans=0; Init();
        for(int i=0;i<n;i++){
            scanf("%d %d",&P[i].x,&P[i].y);
        }
        for(int i=0;i<n;i++){
            InsetHash(P[i]);
        }
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                Point C,D;
                C.x=P[i].x+(P[i].y-P[j].y); C.y=P[i].y-(P[i].x-P[j].x);
                D.x=P[j].x+(P[i].y-P[j].y); D.y=P[j].y-(P[i].x-P[j].x);
                if(Search(C)&&Search(D)){
                    ans++;
                }
                C.x=P[i].x-(P[i].y-P[j].y); C.y=P[i].y+(P[i].x-P[j].x);
                D.x=P[j].x-(P[i].y-P[j].y); D.y=P[j].y+(P[i].x-P[j].x);
                if(Search(C)&&Search(D)){
                    ans++;
                }
            }
        }
        printf("%d\n",ans>>2);
    }
    return 0;
}

 

posted @ 2016-07-06 08:59  キリト  阅读(338)  评论(0编辑  收藏  举报