PKU 2002 Squares(二维点哈希+平方求余法+链地址法)

题目大意:原题链接

给定平面上的N个点,求出这些点一共可以构成多少个正方形。

解题思路:

若正方形为ABCD,A坐标为(x1, y1),B坐标为(x2, y2),则很容易可以推出C和D的坐标。对于特定的A和B坐标,C和D可以在线段AB的上面或者下面,即有两种情况。

            根据构造三角形全等可以得知(很简单,注意下细节,不要把坐标弄混就行)

CD在AB上面x3=x2+(y1-y2),y3=y2+(x2-x1);    x4=x1+(y1-y2),y4=y1+(x2-x1);

CD在AB下面x3=x2-(y1-y2),y3=y2-(x2-x1);      x4=x1-(y1-y2),y4=y1-(x2-x1);

因此只需要枚举点A和点B,然后计算出两种对应的C和D的坐标,判断是否存在即可。这样计算完之后得到的答案是正确答案的4倍,因为正方形的4条边都枚举了,所以答案要右移两位

Insert(int x,int y)采用平方求余法构造哈希函数,链地址法(用类邻接表法实现)处理冲突进行哈希

Judge(int x,int y)通过查找判断CD两点是否同时存在,即能判断是否可以构成正方形

#include<iostream>  
#include<cstring>  
#include<algorithm>  
using namespace std;  
const int maxn=1010;  
const int N=10007;  
int px[maxn],py[maxn];  
struct Node  
{  
    int x,y;  
    int next;  
}node[N];
long long ans;  
int n,cur,Hash[N]; 

void Insert(int x,int y)  
{  
    int h=(x*x+y*y)%N;  
    node[cur].x=x;  
    node[cur].y=y;  
    node[cur].next=Hash[h];  
    Hash[h]=cur++;  
}  
bool Judge(int x,int y)  
{  
    int h=(x*x+y*y)%N;    
    int next=Hash[h];  
    while(next!=-1){  
        if(x==node[next].x&&y==node[next].y) 
            return true;  
        next=node[next].next;  
    }  
    return false;  
}  
  
int main()  
{  
    while(cin>>n,n){  
        memset(Hash,-1,sizeof(Hash));
        cur=0,ans=0;  
        for(int i=0;i<n;i++){  
            cin>>px[i]>>py[i];
            Insert(px[i],py[i]);  
        }  
        for(int i=0;i<n;i++){//先枚举考虑CD在AB上面  
            for(int j=i+1;j<n;j++){  
                int x3=px[j]+(py[i]-py[j]);  
                int y3=py[j]+(px[j]-px[i]);  
                int x4=px[i]+(py[i]-py[j]);  
                int y4=py[i]+(px[j]-px[i]);  
                if(Judge(x3,y3)&&Judge(x4,y4)) ans++;  
            }
        }  
        for(int i=0;i<n;i++){//再枚举考虑CD在AB下面  
            for(int j=i+1;j<n;j++){  
                int x3=px[j]-(py[i]-py[j]);  
                int y3=py[j]-(px[j]-px[i]);  
                int x4=px[i]-(py[i]-py[j]);  
                int y4=py[i]-(px[j]-px[i]);  
                if(Judge(x3,y3)&&Judge(x4,y4)) ans++;  
            }//要判断C点和D点同时存在才能构成正方形   
        }  
        ans>>=2;  
        printf("%lld\n",ans);  
    }  
}  
posted @ 2017-02-19 11:10  despair_ghost  阅读(447)  评论(0编辑  收藏  举报