这是一道几何+快速查找的题目。
根据扩展方向的不同,主要有两种坐标的形式。我们只需要选择想一个方向的扩展,因为我们需要枚举所有的节点。但是这要做还是会有重复的,根据AB求CD坐标和根据AD求BC坐标,其实这两种确定的是一个正方形,所以最后的结果需要除以2。
另,枚举两个点,求得另外两个点,判断求出的这两个点是否在给定的点集中。我使用的是二分查找策略,首先需要对坐标先按照x排序,x相等的话,按照y进行排序。查找过程先对x进行二分的查找,当查找到x时候,但是对应的y坐标不相等时,需要向左右两个方向分别进行查找x值相等的所有组合,判断y值是否和目标y值相等。举例来说,有以下几个点:(0,5) (1,2) (1,3) (1,4) (2,0) 要查找的目标点为(1,4)我们首先二分的时候查找到的是(1,3),这时候需要向两边分别进行查找,具体见代码。
//11219609 c00h00g 2002 Accepted 396K 1032MS G++ 1975B 2013-01-29 17:09:38
//二分跑了一千多毫秒
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct Node{
int x,y;
};
Node point[1005];
int n;
bool bsearch(Node des){
int l=0,r=n-1;
while(l<=r){
int mid=(l+r)>>1;
if(point[mid].x<des.x)
l=mid+1;
else if(point[mid].x>des.x)
r=mid-1;
else if(point[mid].x==des.x){
//继续查找
if(point[mid].y==des.y)
return 1;
else if(point[mid].y>des.y){
int i=mid-1;
while(i>=0&&point[i].x==des.x){
if(point[i].y==des.y)
return 1;
else
i--;
}
return 0;
}
else if(point[mid].y<des.y){
int i=mid+1;
while(i<n&&point[i].x==des.x){
if(point[i].y==des.y)
return 1;
else
i++;
}
return 0;
}
}
}
return 0;
}
int cmp(Node p1,Node p2){
if(p1.x!=p2.x)
return p1.x<p2.x;
else
return p1.y<p2.y;
}
int main(){
while(scanf("%d",&n)&&n){
for(int i=0;i<n;i++)
scanf("%d%d",&point[i].x,&point[i].y);
sort(point,point+n,cmp);
int res=0;
for(int i=0;i<n;i++)
for(int j=0;j<i;j++){
int x1=point[i].x;int y1=point[i].y;
int x2=point[j].x;int y2=point[j].y;
int x3=x1+y1-y2;int y3=y1+x2-x1;
int x4=x2+y1-y2;int y4=y2+x2-x1;
Node tmp1;tmp1.x=x3;tmp1.y=y3;
Node tmp2;tmp2.x=x4;tmp2.y=y4;
if(bsearch(tmp1)&&bsearch(tmp2))
res++;
}
printf("%d\n",res/2);
}
return 0;
}