(zz)简单hash,具体做法是枚举任意两个点,因为有这由两个点所构成的边属于某个正方形那么可以计算出属于该正方形的另外两个点。如有两个点(a1,a2)和(b1,b2),那么如果点(a1+(a2-b2), a2-(a1-b1))和点(b1+(a2-b2), b2-(a1-b1))都存在则这四个点可以构成一个正方形。同时如果点(a1-(a2-b2), a2+(a1-b1))和点(b1-(a2-b2), b2+(a1-b1))存在那么点(a1,a2),(b1,b2),(a1-(a2-b2), a2+(a1-b1))和(b1-(a2-b2), b2+(a1-b1))又可以构成一个正方形,差不多思想就是这个样子,不过好像时间比较长1500多ms,应该还可以优化。
下面是AC代码:
#include<iostream>
using namespace std;
struct point
{
point()
{
index=-1;
next=NULL;
}
point(int index,point* next)
{
this->index=index;
this->next=next;
}
int index;
point* next;
};
int a[1001][2];
bool find(point hash_table[],int,int);
int main()
{
int n,value;
while(scanf("%d",&n)&&n)
{
long result=0;
point hash_table[40001];
for(int e=0;e<n;e++)
{
scanf("%d%d",&a[e][0],&a[e][1]);
value=a[e][0]+a[e][1];
if(value<0)value=-value;
if(hash_table[value].index==-1)hash_table[value].index=e;
else
{
point* p=&hash_table[value];
while(p->next!=NULL)p=p->next;
p->next=new point(e,NULL);
}
}
for(int x=0;x<n;x++)
for(int y=x+1;y<n;y++)
{
int d_x=a[x][0]-a[y][0];
int d_y=a[x][1]-a[y][1];
if(find(hash_table,a[x][0]-d_y,a[x][1]+d_x)&&
find(hash_table,a[y][0]-d_y,a[y][1]+d_x))
result++;
if(find(hash_table,a[x][0]+d_y,a[x][1]-d_x)&&
find(hash_table,a[y][0]+d_y,a[y][1]-d_x))
result++;
}
printf("%ld/n",result/4);
}
return 0;
}
bool find(point hash_table[40001],int x,int y)
{
int value=(x+y)<0?-(x+y):(x+y);
point* p=&hash_table[value];
if(p->index==-1)return false;
while(p!=NULL)
{
if(a[p->index][0]==x&&a[p->index][1]==y)return true;
p=p->next;
}
return false;
}
自己WA代码:
枚举+二分代码
枚举+hash代码
本文介绍了一种通过枚举两点并利用hash表来查找是否存在由这两点构成的正方形的其它两个点的方法。此方法适用于解决特定几何问题,尤其是在点坐标为整数的情况下。
1166

被折叠的 条评论
为什么被折叠?



