Squares POJ - 2002 hash函数

本文介绍了一种高效检测由给定点集构成的正方形数量的方法。通过哈希表映射坐标,利用两层循环而非四层循环减少计算量,避免了时间复杂度过高的问题。

题意是给给定一个数值n

输入n组数,求由n组数能组成多少个正方形、

此题如果直接用4层循环查找的话 时间复杂度是10的12次方

我们选择先找两个点,然后计算出另外两个点,再查找是否给出了这两个点来计算answer

可以把给出的每个点做一个哈希映射,此题选择的是x*x+y*y;


#include<iostream>
#include<cstdio>
#include <cstring>
#define prime 1999
using namespace std;
int n;
struct
{
    int x;
    int y;
}Point[1002];

typedef class HashTable
{
    public:
    int x,y;
    HashTable *next;
    HashTable()
    {
        next=0;
    }
}HashTable;
HashTable* Hash[prime];
void Insert(int k)
{
    int key=(Point[k].x*Point[k].x+Point[k].y*Point[k].y)%prime+1;
    if(!Hash[key])
    {
        HashTable *temp=new HashTable;
        temp->x=Point[k].x;
        temp->y=Point[k].y;
        Hash[key]=temp;

    }
    else
    {
        HashTable *p=Hash[key];
        while(p->next)
        {
            p=p->next;
        }
        p->next=new HashTable;
        p->next->x=Point[k].x;
        p->next->y=Point[k].y;
    }
}
bool Find(int x,int y)
{
    int key=(x*x+y*y)%prime+1;
    if(!Hash[key])
        return false;

    HashTable *p=Hash[key];
    while(p)
    {
        if(p->x==x&&p->y==y)
            return true;
        p=p->next;
    }
    return false;
}
int main()
{
    while(cin>>n&&n)
    {
        int answer=0;
        memset(Hash,0,sizeof(Hash));
        memset(Point,0,sizeof(Point));
        for(int i=1; i<=n; ++i)
        {
            cin>>Point[i].x>>Point[i].y;
            Insert(i);
        }

        for(int i=1; i<n; ++i)
            for(int j=i+1; j<=n; ++j)
            {
                int x1=Point[i].x;
                int y1=Point[i].y;
                int x2=Point[j].x;
                int y2=Point[j].y;

                int  x3=x1+(y1-y2);
                int  y3=y1-(x1-x2);
                int  x4=x2+(y1-y2);
                int  y4=y2-(x1-x2);
                if(Find(x3,y3)&&Find(x4,y4))
                    ++answer;

                 x3=x1-(y1-y2);
                 y3=y1+(x1-x2);
                 x4=x2-(y1-y2);
                 y4=y2+(x1-x2);
                if(Find(x3,y3)&&Find(x4,y4))
                    ++answer;
            }
        cout<<answer/4<<endl;
    }
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值