POJ 2002--Squares
2014-07-26 18:07
483 查看
题目要求四点能组成正方形的个数,若直接枚举四点,会TLE。可以根据正方形公式,题目有提示,正方形旋转90度与原图形重合。
我们可以枚举对角线,只有5*10^5个,根据对角线经过中点旋转,来得到另外的两点。可以形象地理解已知A(x1,y1),C(x2,y2)为正方形对角线,经过旋转AB边在x,y轴上的投影长度会互换调。
即是假设另两点为B(x3,y3),D(x4,y4),正方形ABCD,有:
x3+x4 = x1+x2;
y3+y4 = y1+y2;(对角线中点重叠)
x4-x3 = y1-y2;y4-y3 = x2-x1;(旋转之后边的投影长度互换),解以上方程可得BD。
优化:因为B,D坐标必须为整数,所以以上枚举边时所得式必须得出整除结果,因为我们是从点枚举边,所以j = i+1,即每条边只枚举一次。又因为对角线有两条,在枚举到另一条对角线,最好是不用再判断了,最开始使用了map将点和第几点的i,j对应起来,map比较慢。然后考虑到就算枚举了另一条对角线,也只增加一个正方形,所以最后结果除以2.
Hash函数一直用的不好,Hash保存已给点的坐标,key值为坐标经过变换而得,因为坐标x或y属于(-20000,20000),所以坐标对总共有1.6*10^9个,需要散列处理,经过试验,选择500000左右的素数是比较理想的。 px前面的加权有坐标上限确定。
hash:
我们可以枚举对角线,只有5*10^5个,根据对角线经过中点旋转,来得到另外的两点。可以形象地理解已知A(x1,y1),C(x2,y2)为正方形对角线,经过旋转AB边在x,y轴上的投影长度会互换调。
即是假设另两点为B(x3,y3),D(x4,y4),正方形ABCD,有:
x3+x4 = x1+x2;
y3+y4 = y1+y2;(对角线中点重叠)
x4-x3 = y1-y2;y4-y3 = x2-x1;(旋转之后边的投影长度互换),解以上方程可得BD。
优化:因为B,D坐标必须为整数,所以以上枚举边时所得式必须得出整除结果,因为我们是从点枚举边,所以j = i+1,即每条边只枚举一次。又因为对角线有两条,在枚举到另一条对角线,最好是不用再判断了,最开始使用了map将点和第几点的i,j对应起来,map比较慢。然后考虑到就算枚举了另一条对角线,也只增加一个正方形,所以最后结果除以2.
Hash函数一直用的不好,Hash保存已给点的坐标,key值为坐标经过变换而得,因为坐标x或y属于(-20000,20000),所以坐标对总共有1.6*10^9个,需要散列处理,经过试验,选择500000左右的素数是比较理想的。 px前面的加权有坐标上限确定。
hash:
#include<cstdio> #include<cstring> #include<map> using namespace std; #define maxN 499927 #define maxM 1001 #define maxL 11 struct node { int px,py; node* next; }* hashTab[maxN]; struct _node { int px,py; }point[maxM]; bool check(int x,int y) { int slot = (x*maxL+y)%maxN; node* nowNode; for(nowNode = hashTab[slot];nowNode != NULL;nowNode = nowNode->next) { if(nowNode->px == x&&nowNode->py == y) return true; } return false; } int main() { int N; int i,j; int slot; int squareNum; int x1,x2,x3,x4,y1,y2,y3,y4; node* tmpNode; int nodeNum1,nodeNum2; while(scanf("%d",&N)) { if(!N) return 0; squareNum = 0; memset(hashTab,0,sizeof(hashTab)); for(i = 0;i < N;i++) { scanf("%d%d",&point[i].px,&point[i].py); point[i].px += 20000; point[i].py += 20000; tmpNode = new node; tmpNode->px = point[i].px; tmpNode->py = point[i].py; slot = (point[i].px*maxL+point[i].py)%maxN; tmpNode->next = hashTab[slot]; hashTab[slot] = tmpNode; } for(i = 0;i < N;i++) { x1 = point[i].px; y1 = point[i].py; for(j = i+1;j < N;j++) { x2 = point[j].px; y2 = point[j].py; if((x1+x2+y2-y1)%2 == 0) x3 = (x1+x2+y2-y1)/2; else continue; if((x1+x2+y1-y2)%2 == 0) x4 = (x1+x2+y1-y2)/2; else continue; if((y1+y2+x1-x2)%2 == 0) y3 = (y1+y2+x1-x2)/2; else continue; if((y1+y2+x2-x1)%2 == 0) y4 = (y1+y2+x2-x1)/2; else continue; if(check(x3,y3)&&check(x4,y4)) { squareNum++; } } } printf("%d\n",squareNum/2); } return 0; }
相关文章推荐
- POJ 2002-Squares(hash拉链法-正方形个数)
- POJ 2002 Squares【值得摸索的一道二分+点旋转】
- POJ 2002 Squares
- poj2002 hash+邻接表优化Squares
- poj2002——Squares
- POJ 2002 Squares (Hash)
- poj- 2002-Squares-哈希|除法散列法
- poj-2002-Squares--二分
- poj 2002 :Squares(hash 不解释)
- Poj2002 Squares
- poj 2002 Squares
- poj 2002 Squares
- POJ 2002 Squares 计算集合 点的hash
- zoj 2347 || poj 2002 Squares
- poj 2002 Squares,hash
- POJ2002-Squares-hash+枚举+几何
- POJ-2002 Squares
- poj 2002 Squares
- Poj 2002 Squares(二分&&STL)
- poj 2002 Squares