poj 2805 正方形(维护有序数据+二分查找+枚举)
总时间限制: 8000ms 单个测试点时间限制: 4000ms 内存限制: 65536kB
描述
给出平面上一些点的坐标,统计由这些点可以组成多少个正方形。注意:正方形的边不一定平行于坐标轴。
输入
输入包括多组测试数据。每组的第一行是一个整数n (1 <= n <= 1000),表示平面上点的数目,接下来n行,每行包括两个整数,分别给出一个点在平面上的x坐标和y坐标。输入保证:平面上点的位置是两两不同的,而且坐标的绝对值都不大于20000。最后一组输入数据中n = 0,这组数据表示输入的结束,不用进行处理。
输出
对每组输入数据,输出一行,表示这些点能够组成的正方形的数目。
样例输入
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
样例输出
1
6
1
来源
翻译自Rocky Mountain 2004的试题
这个题最早一次提交是2015年,当时一直没有能力拿下这一个非常裸的题。思路后来就非常明确了,无非先排序,再枚举其中两个点,二分查找剩余两个点即可,但是以前写的一直超时(TLE)。后来学会了使用库函数qsort与bsearch,就用这些实现了一下,发现AC了…所以二分查找不要自己实现,还是用库函数好。
Accepted 392kB 1700ms 1244 B G++ 2分钟前
#include<stdio.h>
#include<stdlib.h>
struct point_type
{
int x,y;
};
int compare(const void* e1,const void* e2)
{
const point_type* p1=(const point_type*) e1;
const point_type* p2=(const point_type*) e2;
if (p1->x!=p2->x)
return p1->x-p2->x;
else
return p1->y-p2->y;
}
int n,num,x1,x2,y1,y2;
point_type p[1000];
point_type* key;
point_type* find;
int main()
{
//freopen("output.txt","w",stdout);
//freopen("input.txt","r",stdin);
key=new point_type;
while (scanf("%d",&n)&&n)
{
num=0;
for (int i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
qsort(p,n,sizeof(point_type),compare);
/*
for (int i=0;i<n;i++)
printf("%d %d\n",p[i].x,p[i].y);
printf("\n");
*/
for (int i=0;i<n;i++)
for (int j=i+1;j<n;j++)
{
x1=p[i].x;
x2=p[j].x;
y1=p[i].y;
y2=p[j].y;
key->x=x2+y1-y2;
key->y=y2+x2-x1;
find=(point_type*)
bsearch((const void*) key,p,n,sizeof(point_type),compare);
if (find==NULL)
continue;
key->x=x1+y1-y2;
key->y=y1+x2-x1;
find=(point_type*)
bsearch((const void*) key,p,n,sizeof(point_type),compare);
if (find==NULL)
continue;
//printf("%d %d\n",i,j);
num++;
}
printf("%d\n",num>>1);
}
return 0;
}