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; }