Squares 2002 poj 哈希 二分

本文介绍了一种算法,用于在给定的星星坐标中找出所有可能形成的正方形。通过使用哈希表和几何验证,该算法能有效地检测出由星星构成的所有正方形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Squares
Time Limit: 3500MS Memory Limit: 65536K
Total Submissions: 19307 Accepted: 7461

Description

A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a polygon such that rotating about its centre by 90 degrees gives the same polygon. It is not the only polygon with the latter property, however, as a regular octagon also has this property. 

So we all know what a square looks like, but can we find all possible squares that can be formed from a set of stars in a night sky? To make the problem easier, we will assume that the night sky is a 2-dimensional plane, and each star is specified by its x and y coordinates. 

Input

The input consists of a number of test cases. Each test case starts with the integer n (1 <= n <= 1000) indicating the number of points to follow. Each of the next n lines specify the x and y coordinates (two integers) of each point. You may assume that the points are distinct and the magnitudes of the coordinates are less than 20000. The input is terminated when n = 0.

Output

For each test case, print on a line the number of squares one can form from the given stars.

Sample Input

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

Sample Output

1
6
1

Source



#include <iostream>
#include<cstring>
using namespace std;
const int prime=1999;
struct node
{int x,y;
};
typedef class HashTable
{
   public:
   int x,y;//标记key值对应的x,y  
   HashTable *next; //当出现地址冲突时,开放寻址  
   HashTable()//Initial  
   {next=0;}
}Hashtable;
node pos[1001];
Hashtable* hash[prime];//hash[]是指针数组,存放地址  
void insert_vist(int k)
{
  int key=((pos[k].x*pos[k].x)+(pos[k].y*pos[k].y))%prime+1;//+1是避免==0  
  if(!hash[key]) //使key从[0~1998]后移到[1~1999]  
  {
    Hashtable*temp=new Hashtable;
    temp->x=pos[k].x;
    temp->y=pos[k].y;
    hash[key]=temp;
  }
  else//hash[key]已存地址,地址冲突
  {
      Hashtable *temp=hash[key];
      while(temp->next)//开放寻址,直至next为空  
      {
          temp=temp->next;
      }
      temp->next=new HashTable;//申请新结点,用next指向,记录x、y  
      temp->next->x=pos[k].x;
      temp->next->y=pos[k].y;
  }

  return ;
}
bool Find(int x,int y)
{
   int key=((x*x)+y*y)%prime+1;
   if(!hash[key])//key对应的地址不存在 
   return false;
   else
   {
      Hashtable *temp=hash[key];
      while(temp)
      {

          if(temp->x==x&&temp->y==y)
          return true;
          temp=temp->next;
      }
   }
   return false;
}
int main()
{
    int n;
    while(cin>>n)
    {
       if(n==0)
       break;
       memset(hash,0,sizeof(hash));//0 <-> NULL  
       for(int k=1;k<=n;k++)
       {
          cin>>pos[k].x>>pos[k].y;
          insert_vist(k);//插入哈希表,标记散点  

       }
       int num=0;//正方形的个数  
       for(int i=1;i<=n-1;i++)
       for(int j=i+1;j<=n;j++)
       {
           int a=pos[j].x-pos[i].x;
           int b=pos[j].y-pos[i].y;
           int x3=pos[i].x+b;
           int y3=pos[i].y-a;
           int x4=pos[j].x+b;
           int y4=pos[j].y-a;
           if(Find(x3,y3)&&Find(x4,y4))
             num++;
             x3=pos[i].x-b;
             y3=pos[i].y+a;
             x4=pos[j].x-b;
             y4=pos[j].y+a;
             if(Find(x3,y3)&&Find(x4,y4))
             num++;
        }
        cout<<num/4<<endl;//同一个正方形枚举了4次  
    }

    return 0;
}



#include <cstdio>
#include <cstring>
#include<iostream>
#include <cmath>
#include <vector>
#include<algorithm>
using namespace std ;
#define eqs 1e-9
struct node{
    double x , y ;
}p[1100] ;
bool cmp(node a,node b)
{
    return ( a.x < b.x || ( a.x == b.x && a.y < b.y ) ) ;
}
bool judge(double x,double y,int n)
{
    int low = 0 , mid , high = n-1 ;
    while( low <= high )
    {
        mid = (low + high) / 2 ;
        if( fabs(p[mid].x-x) < eqs && fabs(p[mid].y-y) < eqs )
            return true ;
        else if( p[mid].x-x > eqs || ( fabs(p[mid].x-x) < eqs && p[mid].y-y > eqs ) )
            high = mid - 1 ;
        else
            low = mid + 1 ;
    }
    return false ;
}
int main()
{
    int n , i , j , num ;
    double x , y , xx , yy ;
    while( scanf("%d", &n) && n )
    {
        num = 0 ;
        for(i = 0 ; i < n ; i++)
        {
            scanf("%lf %lf", &p[i].x, &p[i].y) ;
        }
        sort(p,p+n,cmp) ;
        for(i = 0 ; i < n ; i++)
        {
            for(j = i+1 ; j < n ; j++)
            {
                if( i == j ) continue ;
                x = (p[i].x+p[j].x)/2 ;
                y = (p[i].y+p[j].y)/2 ;
                xx = p[i].x - x ;
                yy = p[i].y - y ;
                if( judge(x+yy,y-xx,n) && judge(x-yy,y+xx,n) )
                {
                    //printf("(%.1lf,%.1lf) (%.1lf,%.1lf) (%.1lf,%.1lf) (%.1lf,%.1lf)\n", p[i].x, p[i].y , p[j].x, p[j].y,x+yy,y-xx,x-yy,y+xx ) ;
                    num++ ;
                }
            }
        }
        printf("%d\n", num/2) ;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值