http://poj.org/problem?id=2002
给出n个坐标,让你求出 这n个坐标里包含有多少个正方形,n《1000
思路:
直接枚举四个点显然TLE,我们可以枚举2个点作为一对顶点点,以公式计算出另外两个点的坐标(逆时针下),
然后我们在 输入的所有点里面查找,看这2个点是否存在 。存在正方形个数+1
真是数学弱到渣。。。。已知一对顶点,计算正方形另外两个点坐标的时候用几何公式。。double再算。。。一直开始一直TLE、、、后来才发现都是int就够了。。。
int xx=tm[i].x+tm[j].x+tm[i].y-tm[j].y;
int yy=tm[i].y+tm[j].y+tm[j].x-tm[i].x;由点i,j作为对角线顶点 ,i点逆时针旋转90度后得到的一个点的坐标应该为(xx/2,yy/2) (不推了。。)
那么判断xx%2 &&yy%2 ,因为题目输入都是int,所以如果答案非整型直接continue;
查找在这用hash, 开放定址法的 二次探测再散列法 解决冲突问题
由于每个正方形会被枚举四次,所以ans 要除四
---------------经过上面处理, 最快只能跑 1.6S.....
后来看到别人blog发现一个地方可以剪枝。。。
即在枚举顶点时 加上判断 if(tm[j].x >=tm[i].x && tm[i].y-tm[j].y<0)
这样就能保证 一个正方形只被枚举一次。。 直接卡掉了3/4的无效操作,到了610ms
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
typedef unsigned __int64 ull;
const double pi=acos(-1.0);
double eps=0.000001;
int n;
int HASH[200007+5];
const ull mod= 200007 ;
struct POINT
{
int x;
int y;
POINT(int a=0, int b=0) { x=a; y=b;}
bool operator <(const POINT&bb)
{
if (x!=bb.x)
return x<bb.x;
else
return y<bb.y;
}
bool operator ==(const POINT& bb)
{
if ( x==bb.x && y==bb.y)
return true;
else
return false;
}
};
POINT tm[1005];
int find(int xx,int yy)
{
ull tt1=xx*239+ yy *113;
int dd=tt1%mod;
int tmp=dd,t=1;
int flag=0;
while(HASH[tmp]!=0)
{
if ( tm[HASH[tmp]].x==xx&&tm[HASH[tmp]].y==yy)
{flag=1;break;}
tmp=(dd+t*t)%mod;
t++;
}
if (!flag) return 0;
else return 1;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if (!n) break;
memset(HASH,0,sizeof(HASH));
int i,j,tx,ty;
for (i=1;i<=n;i++)
{
scanf("%d %d",&tx,&ty);
tm[i].x=tx;
tm[i].y=ty;
ull tmppppp=tx*239+ty*113;
int dd=tmppppp%mod;
int tmp=dd,t=1;
while(HASH[tmp]!=0)
{
tmp=(dd+t*t)%mod;
t++;
}
HASH[tmp]=i;
}
int ans=0;
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
{
if (i==j) continue;
if(tm[j].x >=tm[i].x && tm[i].y-tm[j].y<0)
{
int xx=tm[i].x+tm[j].x+tm[i].y-tm[j].y;
int yy=tm[i].y+tm[j].y+tm[j].x-tm[i].x;
if (xx%2 ||yy%2) continue;
xx/=2;
yy/=2;
if ( find(xx,yy)==0 )
continue;
xx=tm[i].x+tm[j].x+tm[j].y-tm[i].y;
yy=tm[i].y+tm[j].y+tm[i].x-tm[j].x;
if (xx%2 ||yy%2) continue;
xx/=2;
yy/=2;
if ( find(xx,yy)==0) continue;
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}