题目
http://poj.org/problem?id=2002
题意
已知平面内有1000个点,所有点的坐标量级小于20000,求这些点能组成多少个不同的正方形。
思路
如图,将坐标按照升序排列后,首先枚举p1,p2, 并判断p2是否在p1正下方或者左上角(因为每个正方形只有一条最右边或者是右下的边),按照下图计算p3,p4,判断p3,p4是否存在即可。
感想
排序时要注意和左上角这个信息相符,刚写完时用的是左下角,与升序排序不符合,会遗失部分正方形。
代码
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <sstream> #include <map> #include <set> using namespace std; typedef long long ll; typedef pair<int, int> P; const int maxn = 1000; const int base = 2e4 + 4; int n; P a[maxn]; set<int> st; bool upperleft(P p1, P p2){ return p1.first <= p2.first && p1.second < p2.second; } int adhere(P p){ return p.first * base + p.second; } P othercorners(P p1, P p2){ int deltax = p2.first - p1.first; int deltay = p2.second - p1.second; P p3(deltay, -deltax); P p4(deltax + deltay, deltay - deltax); p3.first += p1.first; p4.first += p1.first; p3.second += p1.second; p4.second += p1.second; //printf("P1 (%d, %d), P2 (%d, %d), P3 (%d, %d), P4 (%d, %d) ", // p1.first, p1.second, p2.first, p2.second, p3.first, p3.second, p4.first, p4.second); return P(adhere(p3), adhere(p4)); } int solve(){ int cnt = 0; sort(a, a + n); st.clear(); for(int i = 0;i < n;i++){ st.insert(adhere(a[i])); } for(int i = 0;i < n;i++){ for(int j = i + 1;j < n;j++){ if(upperleft(a[i], a[j])){ //printf("(%d, %d) is on the upper left corner of (%d, %d) ", a[j].first, a[j].second, a[i].first, a[i].second); P corners = othercorners(a[i], a[j]); if(st.find(corners.first) != st.end() && st.find(corners.second) != st.end()){ cnt++; } } } } return cnt; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); #endif // LOCAL while(scanf("%d", &n) == 1 && n){ for(int i = 0;i < n;i++){ scanf("%d%d", &a[i].first, &a[i].second); } int ans = solve(); printf("%d ",ans); } return 0; }