关于#平面#的问题,如何解决?

题目描述
给出平面上一些点(少于50个),坐标都是整数(|xi|,|yi| <= 10^9),有可能重复。
问存在多少个以这些点为顶点的平行于坐标轴的不同矩形。(两个矩形如果四个顶点坐标都相同,就算相同的矩形)
输入格式
第一行一个整数T(T <= 100)表示测试数据的组数 对于每组数据 第一行一个整数n,表示点的数量 下面n行每行两个整数xi,yi表示点的坐标
输出格式
T行,每行一个整数表示以这些点为顶点的平行于坐标轴的矩形个数
样例
样例输入
1
7
0 0
0 1
0 2
1 0
1 1
1 2
0 0
样例输出
3


#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
int main()
{
    int t, n, x, y, count = 0;
    cin >> t;
    for (int i = 0; i < t; i++)
    {
        cin >> n;
        vector<pair<int, int>> points;
        for (int i = 0; i < n; i++)
        {
            cin >> x >> y;
            points.push_back({x, y});
        }
        // 排序
        sort(points.begin(), points.end());
        // 去重
        auto last = unique(points.begin(), points.end());
        points.erase(last, points.end());
        /*
          points[j] +-----------+ points[l]
                    |           |
                    |           |
          points[i] +-----------+ points[k]
        */
        for (size_t i = 0; i < points.size(); i++)
        {
            for (size_t j = i + 1; j < points.size(); j++)
            {
                if (points[i].first == points[j].first)
                {
                    for (size_t k = j + 1; k < points.size(); k++)
                    {
                        if (points[k].first != points[i].first && points[k].second == points[i].second)
                        {
                            for (size_t l = k + 1; l < points.size(); l++)
                            {
                                if (points[l].first == points[k].first && points[l].second == points[j].second)
                                    count++;
                            }
                        }
                    }
                }
            }
        }
    }
    cout << count << endl;
    return 0;
}

#include <algorithm>
#include <cstring>
#include <iostream>
 
using namespace std;
 
typedef pair<int, int> PII;
const int N = 100;
PII arr[N];
int main() {
    int n, sum = 0, t;
    cin >> t;
    while (t--) {
        cin >> n;
        for (int i = 0; i < n; i++)
            cin >> arr[i].first >> arr[i].second;
        sort(arr, arr + n);
        n = unique(arr, arr + n) - arr; // 必须要先排序,再去重,然后才二分查找
        for (int i = 0; i < n; i++) {
 
            int x = arr[i].first + 1, y = arr[i].second + 1;
            // lower_bound是库函数二查找,找到比当前arr[i]的坐标大1的数在什么位置
            int j = lower_bound(arr, arr + n, make_pair(x, y)) - arr;
            sum += n - j;
        }
 
        cout << sum << endl;
    }
 
    return 0;
}

#include<iostream>
#include <math.h>
using namespace std;
double x[50],y[50];
double f[50]= {-65536};
int p=0;
bool isRectangle( double x1,  double y1,
                  double x2,  double y2,
                  double x3,  double y3,
                  double x4,  double y4)
{
    double cx=(x1+x2+x3+x4)/4;
    double cy=(y1+y2+y3+y4)/4;
 
    double dd1=  sqrt(cx-x1)+  sqrt(cy-y1);
    double dd2=  sqrt(cx-x2)+  sqrt(cy-y2);
    double dd3=  sqrt(cx-x3)+  sqrt(cy-y3);
    double dd4=  sqrt(cx-x4)+  sqrt(cy-y4);
    return  abs(dd1 - dd2) < 1E-6 &&
            abs(dd1 - dd3) < 1E-6 &&
            abs(dd1 - dd4) < 1E-6;
}
 
int main()
{
    int count=0;
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        cin >> n;
        for(int j=0; j<n; j++)
        {
            cin >> x[j];
            cin >> y[j];
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
                for(int k=0; k<n; k++)
                    for(int h=0; h<n; h++)
                    {
                        if(isRectangle(x[i],y[i],
                                       x[j],y[j],
                                       x[k],y[k],
                                       x[h],y[h]))
                        {
 
                            count++;
                             double tem=x[i]*y[i]*x[j]*y[j]*x[k]*y[h]*x[h]*y[h];
                            for(int point=0; point<p; point++)
                                if(tem==f[point])
                                {
                                    count--;
                                    break;
                                }
                            f[p++]=tem;
                        }
                    }
        }
    }
    cout << count << endl;
    return 0;
}

采用枚举对角线的方式,二重循环,另外要去重
单次复杂度约为O(N^2)
代码:

#include<bits/stdc++.h>
using namespace std;
int T,n;
struct Node{
    int x,y;
    bool operator<(const Node&a)const{
        return x<a.x||x==a.x&&y<a.y;
    }
    bool operator==(const Node&a)const{
        return x==a.x&&y==a.y;
    }
}a[1009];
struct Squ{
    Node a[4];
    bool operator<(const Squ&A)const{
        return a[1]<A.a[1];
    }
    bool eq(const Squ&A){
        return a[1]==A.a[1]&&a[2]==A.a[2]&&a[3]==A.a[3]&&a[4]==A.a[4];
    }
    bool operator==(const Squ&A)const{
        Squ tmp=*this;
        do{
            if(tmp.eq(A))return 1;
        }while(next_permutation(tmp.a,tmp.a+4));
        return 0;
    }
};
set<Squ>sq;
set<Node>h;
set<Node>::iterator it;
void quchong() {
    h.clear();
    for(int i=1;i<=n;i++)h.insert(a[i]);
    it=h.begin();
    n=h.size();
    int x=0;
    for(;it!=h.end();it++)a[++x]=*it;
}
int main() {
    Node f1,f2;
    cin>>T;
    for(int i=1;i<=T;i++) {
        sq.clear();
        cin>>n;
        for(int j=1;j<=n;j++)cin>>a[j].x>>a[j].y; 
        //枚举对角线
        quchong();//去重同时排序,方便后面的二分查找 
        for(int k=1;k<=n;k++)
            for(int m=k+1;m<=n;m++) {
                f1=(Node){a[m].x,a[k].y},f2=(Node){a[k].x,a[m].y};//另外两点
                if(!(*lower_bound(a+1,a+1+n,f1)==f1&&*lower_bound(a+1,a+1+n,f2)==f2))continue;
                if(lower_bound(a+1,a+1+n,f1)-a==k||lower_bound(a+1,a+1+n,f1)-a==m)continue;
                if(lower_bound(a+1,a+1+n,f2)-a==k||lower_bound(a+1,a+1+n,f2)-a==m)continue;
                Squ tmp;
                tmp.a[0]=a[k];
                tmp.a[1]=f1;
                tmp.a[2]=a[m];
                tmp.a[3]=f2;
                sq.insert(tmp);
            }
        cout<<sq.size()<<endl;
    }
    return 0;
}