zoukankan      html  css  js  c++  java
  • poj 2002 Squares

    题目连接

    http://poj.org/problem?id=2002  

    Squares

    Description

    A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a polygon such that rotating about its centre by 90 degrees gives the same polygon. It is not the only polygon with the latter property, however, as a regular octagon also has this property. 

    So we all know what a square looks like, but can we find all possible squares that can be formed from a set of stars in a night sky? To make the problem easier, we will assume that the night sky is a 2-dimensional plane, and each star is specified by its x and y coordinates. 

    Input

    The input consists of a number of test cases. Each test case starts with the integer n (1 <= n <= 1000) indicating the number of points to follow. Each of the next n lines specify the x and y coordinates (two integers) of each point. You may assume that the points are distinct and the magnitudes of the coordinates are less than 20000. The input is terminated when n = 0.

    Output

    For each test case, print on a line the number of squares one can form from the given stars.

    Sample Input

    4
    1 0
    0 1
    1 1
    0 0
    9
    0 0
    1 0
    2 0
    0 2
    1 2
    2 2
    0 1
    1 1
    2 1
    4
    -2 5
    3 7
    0 0
    5 2
    0

    Sample Output

    1
    6
    1

    题意:给出一些点的集合求能组成正方形的个数。
    思路:直接枚举的话$n = 1000 O(n^4)$ 会超时。考虑换个思路:已知两个点,由正方形的几何特性
    求出另外两个点的坐标,判断是否在点的集合里(哈希,二分,set。。。)都可我用的哈希。
    具体先对所有的点按横坐标,纵坐标从小到大排序。统计个数$tot$,最后的答案即为${tot/2}$(正方形的对称性)
    那么问题来了,如何已知两个点,求另外两个点呢?
    现在给出公式:记$A(x_1,y_1) B(x_2,y_2) overrightarrow {AB} =(x_2-x_1,y_2-y_1)$
    另外两个点$C(x_3, y_3) D(x_4,y_4) $
    $C: x_3 = y_1 - y_2 + x_1 y_3 = x_2 - x_1 + y_1 $
    $D: x_4= y_1 - y_2 + x_2 y_4 = x_2 - x_1 + y_2 $
    证明其实很简单记$overrightarrow{X} = (a,b)$逆时针旋转$eta$度得到$overrightarrow{Y}(x,y)$
    有:$x = acoseta-bsineta y = asineta+bcoseta$ (由三角函数的几何意义易得)
    那么$overrightarrow {AC} = (x_3-x_1,y_3-y_1)$
    $x_3-x_1=(x_2-x_1)coseta - (y_2-y_1)sineta$
    $y_3-y_1=(x_2-x_1)sineta + (y_2-y_1)coseta$ 其中$eta = 90^0$
    所以$x_3 = y_1-y_2+x_1 y_3=x_2-x_1+y_1$
    $overrightarrow {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
    ", ans >> 1);
        }
        return 0;
    }
  • 相关阅读:
    HDU 1525
    kmp模板
    hdu 4616 Game(树形DP)
    hdu 4619 Warm up 2(并查集活用)
    hdu 4614 Vases and Flowers(线段树加二分查找)
    Codeforces 400D Dima and Bacteria(并查集最短路)
    poj 2823 Sliding Window (单调队列)
    hdu 2196 Computer(树形dp)
    hdu 4604 Deque
    最短路径
  • 原文地址:https://www.cnblogs.com/GadyPu/p/4776659.html
Copyright © 2011-2022 走看看