POJ-2002 Squares,哈希模板+数学公式!

                                                       Squares

   题意:二维坐标轴给出n个点求有多少个正方形。

   要是平时做比赛的话毫无疑问会想到用二分去写这道题,但毕竟出现在hash专题里,所以自然用hash去攻克,但是完全没有思路,于是,,网上找了题解,让我感叹的是我们做hash的题怎么知道用哪种hash函数呢。。这道题以坐标平方和再对hash数组大小取余,这样离散化感觉有点钻数据空子,但hash是有处理冲突的能力的,存在冲突怎么办呢,我们可以用链表的形式建立联系,直接在链表中查找就可以了。

   用两层循环枚举然后在hash表中查找另外两个点是否存在,所以这题还有一个很重要的数学公式,那就是:

已知: (x1,y1)  (x2,y2)

则: x3=x1+(y1-y2)   y3= y1-(x1-x2)

        x4=x2+(y1-y2)   y4= y2-(x1-x2)

         x3=x1-(y1-y2)   y3= y1+(x1-x2)

         x4=x2-(y1-y2)   y4= y2+(x1-x2)

  枚举两个点,根据上面的公式得出坐标,再根据坐标关系在hash表中查找。

struct hashmap
{
    int x,y;
    hashmap *next;
    hashmap()
    {
        next=NULL;
    }
}*h[N];
struct node
{
    int x,y;
}a[N];
void insert(int x,int y)
{
    int key=(x*x+y*y)%N;
    if(!h[key])
    {
        hashmap *tmp=new hashmap();
        tmp->x=x,tmp->y=y;
        h[key]=tmp;
    }
    else
    {
        hashmap *tmp=h[key];
        while(tmp->next) tmp=tmp->next;
        tmp->next=new hashmap();
        tmp->next->x=x,tmp->next->y=y;
    }
}
bool find(int x,int y)
{
    int key=(x*x+y*y)%N;
    hashmap *tmp=h[key];
    while(tmp)
    {
        if(tmp->x==x&&tmp->y==y) return true;
        tmp=tmp->next;
    }
    return false;
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        memset(h,0,sizeof(h));
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a[i].x,&a[i].y);
            insert(a[i].x,a[i].y);
        }
        int ans=0;
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
        {
            int x1=a[i].x+a[i].y-a[j].y,y1=a[i].y-a[i].x+a[j].x;
            int x2=a[j].x+a[i].y-a[j].y,y2=a[j].y-a[i].x+a[j].x;
            if(find(x1,y1)&&find(x2,y2)) ans++;
            x1=a[i].x+a[j].y-a[i].y,y1=a[i].y+a[i].x-a[j].x;
            x2=a[j].x+a[j].y-a[i].y,y2=a[j].y+a[i].x-a[j].x;
            if(find(x1,y1)&&find(x2,y2)) ans++;
        }
        printf("%d\n",ans/4);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值