poj 2805 正方形(维护有序数据+二分查找+枚举)

poj 2805 正方形(维护有序数据+二分查找+枚举)
总时间限制: 8000ms 单个测试点时间限制: 4000ms 内存限制: 65536kB

描述
给出平面上一些点的坐标,统计由这些点可以组成多少个正方形。注意:正方形的边不一定平行于坐标轴。

输入
输入包括多组测试数据。每组的第一行是一个整数n (1 <= n <= 1000),表示平面上点的数目,接下来n行,每行包括两个整数,分别给出一个点在平面上的x坐标和y坐标。输入保证:平面上点的位置是两两不同的,而且坐标的绝对值都不大于20000。最后一组输入数据中n = 0,这组数据表示输入的结束,不用进行处理。

输出
对每组输入数据,输出一行,表示这些点能够组成的正方形的数目。

样例输入
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

样例输出
1
6
1

来源
翻译自Rocky Mountain 2004的试题

这个题最早一次提交是2015年,当时一直没有能力拿下这一个非常裸的题。思路后来就非常明确了,无非先排序,再枚举其中两个点,二分查找剩余两个点即可,但是以前写的一直超时(TLE)。后来学会了使用库函数qsort与bsearch,就用这些实现了一下,发现AC了…所以二分查找不要自己实现,还是用库函数好。

Accepted    392kB   1700ms  1244 B  G++ 2分钟前
#include<stdio.h>
#include<stdlib.h>

struct point_type
{
    int x,y;
};

int compare(const void* e1,const void* e2)
{
    const point_type* p1=(const point_type*) e1;
    const point_type* p2=(const point_type*) e2;
    if (p1->x!=p2->x)
        return p1->x-p2->x;
    else
        return p1->y-p2->y;
}

int n,num,x1,x2,y1,y2;
point_type p[1000]; 
point_type* key;
point_type* find;

int main()
{
    //freopen("output.txt","w",stdout);
    //freopen("input.txt","r",stdin);
    key=new point_type;
    while (scanf("%d",&n)&&n)
    {
        num=0;
        for (int i=0;i<n;i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        qsort(p,n,sizeof(point_type),compare);
        /*
        for (int i=0;i<n;i++)
            printf("%d %d\n",p[i].x,p[i].y);
        printf("\n");
        */
        for (int i=0;i<n;i++)
            for (int j=i+1;j<n;j++)

                {
                    x1=p[i].x;
                    x2=p[j].x;
                    y1=p[i].y;
                    y2=p[j].y;
                    key->x=x2+y1-y2;
                    key->y=y2+x2-x1;
                    find=(point_type*) 
                    bsearch((const void*) key,p,n,sizeof(point_type),compare);
                    if (find==NULL)
                        continue;
                    key->x=x1+y1-y2;
                    key->y=y1+x2-x1;
                    find=(point_type*) 
                    bsearch((const void*) key,p,n,sizeof(point_type),compare);
                    if (find==NULL)
                        continue;
                    //printf("%d %d\n",i,j);
                    num++;
                }
        printf("%d\n",num>>1);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值