POJ 2002 hash(枚举+哈希) 或者 枚举+二分

本文介绍了一种通过枚举两点并利用hash表来查找是否存在由这两点构成的正方形的其它两个点的方法。此方法适用于解决特定几何问题,尤其是在点坐标为整数的情况下。

(zz)简单hash,具体做法是枚举任意两个点,因为有这由两个点所构成的边属于某个正方形那么可以计算出属于该正方形的另外两个点。如有两个点(a1,a2)和(b1,b2),那么如果点(a1+(a2-b2), a2-(a1-b1))和点(b1+(a2-b2), b2-(a1-b1))都存在则这四个点可以构成一个正方形。同时如果点(a1-(a2-b2), a2+(a1-b1))和点(b1-(a2-b2), b2+(a1-b1))存在那么点(a1,a2),(b1,b2),(a1-(a2-b2), a2+(a1-b1))和(b1-(a2-b2), b2+(a1-b1))又可以构成一个正方形,差不多思想就是这个样子,不过好像时间比较长1500多ms,应该还可以优化。

下面是AC代码:

#include<iostream>
using namespace std;
struct point
{
 point()
 {
  index=-1;
  next=NULL;
 }
 point(int index,point* next)
 {
  this->index=index;
  this->next=next;
 }
 int index;
 point* next;
};
int a[1001][2];
bool find(point hash_table[],int,int);
int main()
{
 int n,value;
 while(scanf("%d",&n)&&n)
 {
  long result=0;
  point hash_table[40001];
  for(int e=0;e<n;e++)
  {
   scanf("%d%d",&a[e][0],&a[e][1]);
   value=a[e][0]+a[e][1];
   if(value<0)value=-value;
   if(hash_table[value].index==-1)hash_table[value].index=e;
   else
   {
    point* p=&hash_table[value];
    while(p->next!=NULL)p=p->next;
    p->next=new point(e,NULL);
   }
  }
  for(int x=0;x<n;x++)
   for(int y=x+1;y<n;y++)
   {
    int d_x=a[x][0]-a[y][0];
    int d_y=a[x][1]-a[y][1];
    if(find(hash_table,a[x][0]-d_y,a[x][1]+d_x)&&
     find(hash_table,a[y][0]-d_y,a[y][1]+d_x))
     result++;
    if(find(hash_table,a[x][0]+d_y,a[x][1]-d_x)&&
     find(hash_table,a[y][0]+d_y,a[y][1]-d_x))
     result++;
   }
  printf("%ld/n",result/4);
 }
 return 0;

bool find(point hash_table[40001],int x,int y)
{
 int value=(x+y)<0?-(x+y):(x+y);
 point* p=&hash_table[value];
 if(p->index==-1)return false;
 while(p!=NULL)
 {
  if(a[p->index][0]==x&&a[p->index][1]==y)return true;
  p=p->next;
 }
 return false;
}

自己WA代码:

枚举+二分代码

枚举+hash代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值