[POJ 2002]Squares[二分][数学]

题目链接: [POJ 2002]Squares[二分][数学]

题意分析:

平面中有n个点,求这些点能组成多少个正方形?

解题思路:

最多1e3个点,四个点枚举肯定超时,必须控制在两个点以内。那么两个点可行吗?下面这幅图可以说明可行:

[POJ 2002]Squares[二分][数学]_第1张图片

当一条边确定以后,由等边三角形的特性,旁边的两个点也能枚举出来。

所以有(i是a点,j是b点):

temp.x = p[i].x + (p[i].y - p[j].y);
temp.y = p[i].y + (p[j].x - p[i].x);

temp.x = p[j].x + (p[i].y - p[j].y);
temp.y = p[j].y + (p[j].x - p[i].x);

然后用二分搜索查找点是否在图中即可。

由于经过坐标排序后,每个矩形会被枚举两次,最终答案要除以2。

例如上图,当枚举边cd和边bd时会枚举到上图的矩形。

个人感受:

第一想法是枚举两条边= =。发现也是复杂度其高啊。一条边出其它点,这种做法真是对我等数学渣的摧残啊。

具体代码如下:

#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#define lowbit(x) (x & (-x))
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1  1
#define ll long long
#define pii pair<int, int>
#define pr(x) cout << #x << " = " << (x) << '\n';
using namespace std;

const int INF = 0x7f7f7f7f;
const int MAXN = 1e3 + 111;

struct P {
    int x, y;
    bool operator < (const P &t)const {
        if (x == t.x) return y < t.y;
        return x < t.x;
    }
}p[MAXN], temp;

bool binary(int l, int r) {
    if (l > r) return 0;
    int m = (l + r) / 2;
    if (p[m].x == temp.x && p[m].y == temp.y) return 1;
    else if (temp < p[m]) return binary(l, m - 1);
    else return binary(m + 1, r);
}

int main()
{
    #ifdef LOCAL
    freopen("C:\\Users\\apple\\Desktop\\in.txt", "r", stdin);
    #endif
    int n;
    while (~scanf("%d", &n) && n) {
        for (int i = 0; i < n; ++i) scanf("%d%d", &p[i].x, &p[i].y);
        sort(p, p + n);
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                temp.x = p[i].x + (p[i].y - p[j].y);
                temp.y = p[i].y + (p[j].x - p[i].x);
                //cout << 1 << ':' << temp.x << ' ' << temp.y << '\n';
                if (!binary(0, n - 1)) continue;
                temp.x = p[j].x + (p[i].y - p[j].y);
                temp.y = p[j].y + (p[j].x - p[i].x);
                //cout << 2 << ':' << temp.x << ' ' << temp.y << '\n';
                if (!binary(0, n - 1)) continue;
                ++ans;
            }
        }
        printf("%d\n", ans/2);
    }
    return 0;
}


你可能感兴趣的:(正方形)