您的位置:首页 > 其它

[poj2002]Squares_hash

2018-03-22 07:57 453 查看

Squares poj-2002

    题目大意:在笛卡尔坐标系中给出n个点,求这些点可以构成多少个正方形。

    注释:$1\le n\le 10^3$,$-2\cdot 10^3\le x , y\le 2\cdot 10^3$.

      想法:最基本的办法是n个点中枚举三个点,然后用桶判断第四个点是否存在。然后我们想一想这个方法怎么优化,首先,枚举三个点我们可以进而优化成为枚举一条边,然后判断可能出现的两个正方形是否存在,时间复杂度$O(n^2)$。对于空间复杂度,4000*4000的桶显然开不下,我们自然而然想到hash处理。但是横纵坐标还存在负权值,故此我们期望找到一个即不区分正负,但是用能将点期望离散开的hash计算方式。首先想到|x|+|y|。但是这种方式并不能很好的将所有点都离散开,更容易想到x*x+y*y。上下的就是细节的事情了。

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define SIZE 4000010
#define mod 99991//关于hash的mod数
using namespace std;
typedef long long ll;
int head[2*SIZE];
int tot;//总点数
int nxt[2*SIZE];
struct Node
{
int x;
int y;
}poi[1001000];//单个的点
Node val[SIZE];//hash中点的横纵坐标
void insert(int a)//插入一个点
{
int value=(poi[a].x*poi[a].x%mod+poi[a].y*poi[a].y%mod)%mod;
tot++;
nxt[tot]=head[value];
head[value]=tot;
val[tot].x=poi[a].x;
val[tot].y=poi[a].y;
}
bool find(int x,int y)//寻找横纵坐标分别为x,y的点是否存在
{
int value=(x*x%mod+y*y%mod)%mod;
for(int i=head[value];i;i=nxt[i])
{
if(poi[i].x==x&&poi[i].y==y) return true;
}
return false;
}
ll ans=0;//统计答案
void original()//初始化
{
tot=0;
memset(head,0,sizeof head);
memset(poi,0,sizeof poi);
ans=0;
}
int main()
{
ans=0;
int n;
while(1)
{
original();
scanf("%d",&n);
if(!n) return 0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&poi[i].x,&poi[i].y);
insert(i);
}
int x1=0;int y1=0;
int x2=0;int y2=0;
int x3=0;int y3=0;
int x4=0;int y4=0;
for(int i=1;i<=n;i++)//枚举两个点,判断是否存在相应的正方形
{
x1=poi[i].x;y1=poi[i].y;
for(int j=i+1;j<=n;j++)//由于我check的方式是采取continue的方式,所以需要写两个
{						//关于j的for循环
x2=poi[j].x;y2=poi[j].y;
if(x1==x2&&y1==y2) continue;
x3=x1-y2+y1;
y3=y1+x2-x1;
if(!find(x3,y3)) continue;
x4=x2-y2+y1;
y4=y2+x2-x1;
if(!find(x4,y4)) continue;
ans++;
}
for(int j=i+1;j<=n;j++)
{
x2=poi[j].x;y2=poi[j].y;
if(x1==x2&&y1==y2) continue;
x3=x1-y1+y2;
y3=y1+x1-x2;
if(!find(x3,y3)) continue;
x4=x2-y1+y2;
y4=y2+x1-x2;
if(!find(x4,y4)) continue;
ans++;
}
}
printf("%lld\n",ans/4);//不要忘记答案除以4
}
}

     小结:我们并不能枚举一条边然后向一个方向枚举,证明在此省略。

        不要忘记如果枚举的两个点坐标相同,那么答案是一定会增加的,所以我们将这样的情况舍去。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: