原题链接:http://poj.org/problem?id=2002
题意:给出一些点的集合求能组成正方形的个数。
思路:直接枚举的话
n=1000 O(n4)
会超时。考虑换个思路:已知两个点,由正方形的几何特性
求出另外两个点的坐标,判断是否在点的集合里(哈希,二分,set。。。)都可我用的哈希。
具体先对所有的点按横坐标,纵坐标从小到大排序。统计个数
tot
,最后的答案即为
tot/2
(正方形的对称性)
那么问题来了,如何已知两个点,求另外两个点呢?
现在给出公式:记
A(x1,y1) B(x2,y2) AB−→−=(x2−x1,y2−y1)
另外两个点
C(x3,y3) D(x4,y4)
C: x3=y1−y2+x1 y3=x2−x1+y1
D: x4=y1−y2+x2 y4=x2−x1+y2
证明其实很简单记
X→=(a,b)
逆时针旋转
β
度得到
Y→(x,y)
有:
x=acosβ−bsinβ y=asinβ+bcosβ
(由三角函数的几何意义易得)
那么
AC−→−=(x3−x1,y3−y1)
x3−x1=(x2−x1)cosβ−(y2−y1)sinβ
y3−y1=(x2−x1)sinβ+(y2−y1)cosβ
其中
β=900
所以
x3=y1−y2+x1 y3=x2−x1+y1
BD−→−
同理(注意向量的方向和旋转方向)
原谅我孱弱的语文水平写的太挫了凑合看吧/(ㄒoㄒ)/~~
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<map>
using std::map;
using std::abs;
using std::sort;
using std::pair;
using std::vector;
using std::multimap;
#define pb(e) push_back(e)
#define sz(c) (int)(c).size()
#define mp(a, b) make_pair(a, b)
#define all(c) (c).begin(), (c).end()
#define iter(c) __typeof((c).begin())
#define cls(arr, val) memset(arr, val, sizeof(arr))
#define cpresent(c, e) (find(all(c), (e)) != (c).end())
#define rep(i, n) for(int i = 0; i < (int)n; i++)
#define tr(c, i) for(iter(c) i = (c).begin(); i != (c).end(); ++i)
const int N = 40007;
const int INF = 0x3f3f3f3f;
struct P {
int x, y;
P() {}
P(int i , int j) :x(i), y(j) {}
inline bool operator<(const P &k) const {
return x == k.x ? y < k.y : x < k.x;
}
}A[N];
struct Hash_Set {
int tot, head[N];
struct edge { int x, y, next; }G[N];
inline void init() {
tot = 0, cls(head, -1);
}
inline void insert(P &k) {
int u = abs(k.x + k.y) % N;
G[tot] = (edge){ k.x, k.y, head[u] }; head[u] = tot++;
}
inline bool find(P k) {
int u = abs(k.x + k.y) % N;
for(int i = head[u]; ~i; i = G[i].next) {
edge &e = G[i];
if(k.x == e.x && k.y == e.y) return true;
}
return false;
}
}hash;
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w+", stdout);
#endif
int n, x1, x2, x3, x4, y1, y2, y3, y4, ans;
while(~scanf("%d", &n), n) {
hash.init();
rep(i, n) {
scanf("%d %d", &A[i].x, &A[i].y);
hash.insert(A[i]);
}
sort(A, A + n);
ans = 0;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
x1 = A[i].x, y1 = A[i].y;
x2 = A[j].x, y2 = A[j].y;
x3 = y1 - y2 + x1, y3 = x2 - x1 + y1;
x4 = y1 - y2 + x2, y4 = x2 - x1 + y2;
if(hash.find(P(x3, y3)) && hash.find(P(x4, y4))) ans++;
}
}
printf("%d\n", ans >> 1);
}
return 0;
}