POJ-2002 Squares---绕点旋转+Hash
题目链接:
https://vjudge.net/problem/POJ-2002
题目大意:
有一堆平面散点集,任取四个点,求能组成正方形的不同组合方式有多少。
相同的四个点,不同顺序构成的正方形视为同一正方形。
解题思路:
直接四个点四个点地枚举肯定超时的,不可取。
普遍的做法是:先枚举两个点(这两个点是正方形的一条边),通过数学公式得到另外2个点,使得这四个点能够成正方形。然后检查散点集中是否存在计算出来的那两个点,若存在,说明有一个正方形。
但这种做法会使同一个正方形按照不同的顺序被枚举了四次,因此最后的结果要除以4.
已知点(x1, y1),(x2, y2),可求出下面两种可能
求出另外两个点之后直接在不在hash表中(之前用二分一直超时)
关于点(x1, y1)绕点(x0, y0)逆时针旋转β度得到(x2, y2)的公式:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<map> 6 #include<set> 7 #include<cmath> 8 #include<algorithm> 9 #include<vector> 10 #define lowbot(i) (i&(-i)) 11 //#define Rotate(a, b) node(a.x + a.y - b.y, a.y + b.x - a.x) 12 using namespace std; 13 typedef long long ll; 14 const int maxn = 1000 + 10; 15 const int mod = 9973; 16 struct node 17 { 18 int x, y; 19 node(){} 20 node(int x, int y):x(x), y(y){} 21 }; 22 struct hashtable 23 { 24 int x, y; 25 hashtable * next; 26 hashtable() 27 { 28 next = 0; 29 } 30 }; 31 hashtable * Hash[mod]; 32 void Hash_Insert(node a) 33 { 34 int key = (a.x * a.x + a.y * a.y) % mod; 35 if(!Hash[key]) 36 { 37 hashtable * p = new hashtable; 38 p->x = a.x; 39 p->y = a.y; 40 Hash[key] = p; 41 } 42 else 43 { 44 hashtable *p = Hash[key]; 45 while(p->next)p=p->next; 46 hashtable* temp = new hashtable; 47 temp->x = a.x; 48 temp->y = a.y; 49 p->next = temp; 50 } 51 } 52 bool Find(node a) 53 { 54 int key = (a.x * a.x + a.y * a.y) % mod; 55 if(!Hash[key])return false; 56 else 57 { 58 hashtable * temp = Hash[key]; 59 while(temp) 60 { 61 if(temp->x == a.x && temp->y == a.y) 62 return true; 63 temp = temp->next; 64 } 65 } 66 return false; 67 } 68 node a[maxn]; 69 70 node Rotate(node a, node b)//点b绕着点a逆时针旋转90度的坐标 71 { 72 int x = (b.x - a.x) * 0 - (b.y - a.y) * 1 + a.x; 73 int y = (b.x - a.x) * 1 + (b.y - a.y) * 0 + a.y; 74 return node(x, y); 75 } 76 77 int main() 78 { 79 int n; 80 while(scanf("%d", &n) != EOF && n) 81 { 82 memset(Hash, 0, sizeof(Hash)); 83 for(int i = 1; i <= n; i++) 84 { 85 scanf("%d%d", &a[i].x, &a[i].y); 86 Hash_Insert(a[i]); 87 } 88 int ans = 0; 89 node x, y; 90 for(int i = 1; i <= n; i++) 91 { 92 for(int j = i + 1; j <= n; j++) 93 { 94 x = Rotate(a[i], a[j]); 95 y = Rotate(x, a[i]); 96 if(Find(x) && Find(y))ans++; 97 //cout<<i<<" "<<j<<" "<<x.x<<" "<<x.y<<" "<<y.x<<" "<<y.y<<endl; 98 x = Rotate(a[j], a[i]); 99 y = Rotate(x, a[j]); 100 if(Find(x) && Find(y))ans++; 101 } 102 } 103 printf("%d\n", ans / 4); 104 } 105 return 0; 106 }
越努力,越幸运