2002 Squares 平面点集能组成多少正方形 哈希表

Squares
Time Limit: 3500MS   Memory Limit: 65536K
Total Submissions: 8065   Accepted: 2718

Description

A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a polygon such that rotating about its centre by 90 degrees gives the same polygon. It is not the only polygon with the latter property, however, as a regular octagon also has this property.

So we all know what a square looks like, but can we find all possible squares that can be formed from a set of stars in a night sky? To make the problem easier, we will assume that the night sky is a 2-dimensional plane, and each star is specified by its x and y coordinates.

Input

The input consists of a number of test cases. Each test case starts with the integer n (1 <= n <= 1000) indicating the number of points to follow. Each of the next n lines specify the x and y coordinates (two integers) of each point. You may assume that the points are distinct and the magnitudes of the coordinates are less than 20000. The input is terminated when n = 0.

Output

For each test case, print on a line the number of squares one can form from the given stars.

Sample Input

4
1 0
0 1
1 1
0 0
9
0 0
1 0
2 0
0 2
1 2
2 2
0 1
1 1
2 1
4
-2 5
3 7
0 0
5 2
0

Sample Output

1
6
1
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int HASHING=2100;//important
const int BLOCK=20001;//考虑坐标为负的情况
int hash_table[HASHING+1];
int hash(int x)//构建哈希表
{
    int ret;
    ret=x%HASHING;
    while(hash_table[ret]!=-1&&hash_table[ret]!=x) ret=(ret+1)%HASHING;
    hash_table[ret]=x;
    return ret;
}//important
int vis[HASHING+10][HASHING+10];
struct Point
{
    int x,y;
};
Point a[1100];
double x[3],y[3];
double _fabs(double x){return x>0?x:-x;}
void cal(int i,int j)//已知正方形对角线坐标,求其余两个顶点坐标
{
    double x0=(double)(a[i].x+a[j].x)/2,y0=(double)(a[i].y+a[j].y)/2;
    if((a[j].y-a[i].y)*(a[j].x-a[i].x)>0)
    {
        x[1]=x0-_fabs(a[j].y-a[i].y)/2;
        x[2]=x0+_fabs(a[j].y-a[i].y)/2;
        y[1]=y0+_fabs(a[j].x-a[i].x)/2;
        y[2]=y0-_fabs(a[j].x-a[i].x)/2;
    }
    else
    {
        x[1]=x0-_fabs(a[j].y-a[i].y)/2;
        x[2]=x0+_fabs(a[j].y-a[i].y)/2;
        y[1]=y0-_fabs(a[j].x-a[i].x)/2;
        y[2]=y0+_fabs(a[j].x-a[i].x)/2;
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)==1&&n)
    {
        memset(hash_table,-1,sizeof(hash_table));//初始化哈希表  important
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a[i].x,&a[i].y);
            vis[hash(a[i].x+BLOCK)][hash(a[i].y+BLOCK)]=1;
        }
        long long cnt=0;
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                cal(i,j);
                int t1=(int)x[1],t2=(int)x[2],t3=(int)y[1],t4=(int)y[2];//(t1,t3),(t2,t4)
                if(t1!=x[1]||t2!=x[2]||t3!=y[1]||t4!=y[2])continue;
                if(vis[hash(t1+BLOCK)][hash(t3+BLOCK)]&&vis[hash(t2+BLOCK)][hash(t4+BLOCK)]) cnt++;
                //if(i==0&&j==3) cout<<t1<<"..."<<t2<<"..."<<t3<<"..."<<t4<<endl;
            }
        }
        cout<<cnt/2<<endl;
    }
    return 0;
}
/*
先将读入的n个点的坐标按照其x坐标作为关键值进行hash,枚举每两个不同的点,将他们作为某个正方形的对角线,
算出两外的两个点,然后对于新算出的两个点的x坐标进行hash查找,对于x相同的点,判断y是否也相同,若相同,
则继续hash另一个点的坐标,若两次都能找到则正方形个数加1。在哈希判断时若找到相同的则直接退出本次查找,
否则一直查找到链表的末尾,表示没有以该两点作为对角线的正方形。
*/

你可能感兴趣的:(struct,table,Integer,input,each,output)