题意是给给定一个数值n
输入n组数,求由n组数能组成多少个正方形、
此题如果直接用4层循环查找的话 时间复杂度是10的12次方
我们选择先找两个点,然后计算出另外两个点,再查找是否给出了这两个点来计算answer
可以把给出的每个点做一个哈希映射,此题选择的是x*x+y*y;
#include<iostream>
#include<cstdio>
#include <cstring>
#define prime 1999
using namespace std;
int n;
struct
{
int x;
int y;
}Point[1002];
typedef class HashTable
{
public:
int x,y;
HashTable *next;
HashTable()
{
next=0;
}
}HashTable;
HashTable* Hash[prime];
void Insert(int k)
{
int key=(Point[k].x*Point[k].x+Point[k].y*Point[k].y)%prime+1;
if(!Hash[key])
{
HashTable *temp=new HashTable;
temp->x=Point[k].x;
temp->y=Point[k].y;
Hash[key]=temp;
}
else
{
HashTable *p=Hash[key];
while(p->next)
{
p=p->next;
}
p->next=new HashTable;
p->next->x=Point[k].x;
p->next->y=Point[k].y;
}
}
bool Find(int x,int y)
{
int key=(x*x+y*y)%prime+1;
if(!Hash[key])
return false;
HashTable *p=Hash[key];
while(p)
{
if(p->x==x&&p->y==y)
return true;
p=p->next;
}
return false;
}
int main()
{
while(cin>>n&&n)
{
int answer=0;
memset(Hash,0,sizeof(Hash));
memset(Point,0,sizeof(Point));
for(int i=1; i<=n; ++i)
{
cin>>Point[i].x>>Point[i].y;
Insert(i);
}
for(int i=1; i<n; ++i)
for(int j=i+1; j<=n; ++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-(x1-x2);
int x4=x2+(y1-y2);
int y4=y2-(x1-x2);
if(Find(x3,y3)&&Find(x4,y4))
++answer;
x3=x1-(y1-y2);
y3=y1+(x1-x2);
x4=x2-(y1-y2);
y4=y2+(x1-x2);
if(Find(x3,y3)&&Find(x4,y4))
++answer;
}
cout<<answer/4<<endl;
}
}

本文介绍了一种高效检测由给定点集构成的正方形数量的方法。通过哈希表映射坐标,利用两层循环而非四层循环减少计算量,避免了时间复杂度过高的问题。

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



