POJ 2002 Squares

POJ_2002

    首先一个很直观的思路就是枚举4个顶点,然后判断是否能构成正方形,但是这样的复杂度十分高。

    但实际上对于确定一个正方形来说,只要有对角线上的两个点就可以了,或者一条边上的两个点也可以,只不过这时就有两种可能罢了。于是我们不妨只枚举两个顶点,然后去查找另外两个顶点是否存在。

    对于查找顶点当然可以排序后二分,但也有更直接一点方法,用哈希表存即可。

#include<stdio.h>
#include<string.h>
#define MAXD 1010
#define HASH 100003
struct point
{
int x, y;
}p[MAXD];
int N, head[HASH], next[MAXD];
int hash(int x, int y)
{
int h = x * 131 + y;
return (h & 0x7fffffff) % HASH;
}
void insert(int s)
{
int h = hash(p[s].x, p[s].y);
next[s] = head[h];
head[h] = s;
}
void init()
{
int i, j, k;
memset(head, -1, sizeof(head));
for(i = 0; i < N; i ++)
{
scanf("%d%d", &p[i].x, &p[i].y);
insert(i);
}
}
int find(int x, int y)
{
int i, h = hash(x, y);
for(i = head[h]; i != -1; i = next[i])
if(p[i].x == x && p[i].y == y)
break;
return i != -1;
}
int check(int s1, int s2)
{
int i, h, x1, y1, x2, y2, t;
if((p[s1].x + p[s2].x + p[s1].y + p[s2].y) % 2 == 1)
return 0;
x1 = (p[s1].x + p[s2].x + p[s1].y - p[s2].y) / 2;
y1 = (p[s1].y + p[s2].y - p[s1].x + p[s2].x) / 2;
if(find(x1, y1))
{
x2 = (p[s1].x + p[s2].x - p[s1].y + p[s2].y) / 2;
y2 = (p[s1].x - p[s2].x + p[s1].y + p[s2].y) / 2;
if(find(x2, y2))
return 1;
}
return 0;
}
void solve()
{
int i, j, k;
long long int ans = 0;
for(i = 0; i < N; i ++)
for(j = i + 1; j < N; j ++)
if(check(i, j))
++ ans;
printf("%lld\n", ans / 2);
}
int main()
{
for(;;)
{
scanf("%d", &N);
if(!N)
break;
init();
solve();
}
return 0;
}


你可能感兴趣的:(poj)