POJ 2002 Squares 解题报告(哈希 开放寻址 & 链式)
经典好题。
题意是要我们找出所有的正方形。1000点,只有枚举咯。
如图,如果我们知道了正方形A,B的坐标,便可以推测出C,D两点的坐标。反之,遍历所有点作为A,B点,看C,D点是否存在。存在的话正方形数+1。

假设A点坐标为(x1,y1),B点坐标为(x2,y2),则根据三角形全等,易知
C点坐标:( x1+(y2-y1),y1-(x2-x1) )
D点坐标:( x2+(y2-y1),y2-(x2-x1) )
当然,如果我们遍历任意两个点,一个正方形将会被计数四次(四条边)。我们可以只判断斜率>=0的边,这条边在正方形的上方(如图AB边),这样不用重复验证四次了。
过程搞清楚了,下面要解决的就是如何判断C,D点是否存在了。
最简单的办法,直接使用set。我们把出现的点加到set里,判断时用find函数即可。当然,时效比较差。笔者测试是1000MS+。
而后,我们也可以使用二分查找。
当然,最快还是hash了。hash分为两种,开放寻址和链式,来解决冲突。在网上搜了很多解题报告,发现大家很多把链式叫做开放寻址……百度百科上有说明,大家可以看一下:http://baike.baidu.com/view/3140124.htm
下面,贴代码:
开放寻址,POJ测试最快是219MS,125MS级别的代码不知是如何实现的==
#include <cstdio>
#include <cstring> int prime[]={,,,,,,,}; int x[],y[];
int savex[],savey[];
bool hash[]; inline int calHash(int x,int y)
{
return ((x<<)^y)&;
} void insert(int x,int y)
{
int h=calHash(x,y);
int add=prime[(x^y)&];
while(hash[h] && (savex[h]!=x || savey[h]!=y))
{
h+=add;
h&=;
}
hash[h]=true;
savex[h]=x;
savey[h]=y;
} bool find(int x,int y)
{
int h=calHash(x,y);
int add=prime[(x^y)&];
while(hash[h] && (savex[h]!=x || savey[h]!=y))
{
h+=add;
h&=;
}
if(hash[h] && savex[h]==x && savey[h]==y)
return true;
return false;
} bool calK(int a,int b)
{
if(x[a]==x[b])
return false;
if(y[a]==y[b])
return true;
if(((x[a]-x[b])&(<<))==((y[a]-y[b])&(<<)))
return true;
return false;
} inline int Abs(int n)
{
return n<?-n:n;
} int main()
{
// freopen("in.txt","r",stdin);
int n;
while(~scanf("%d",&n) && n)
{
memset(hash,,sizeof(hash));
for(int i=;i<n;i++)
{
scanf("%d%d",x+i,y+i);
insert(x[i],y[i]);
} int count=;
for(int i=;i<n;i++)
for(int k=i+;k<n;k++)
{
if(calK(i,k))
{
int _y=Abs(y[i]-y[k]);
int _x=Abs(x[i]-x[k]);
if(find(x[i]+_y,y[i]-_x) &&
find(x[k]+_y,y[k]-_x))
count++;
}
}
printf("%d\n",count);
}
}
链式,即发现冲突就在当前位置加一个槽。POJ上最快319MS。当然,每次新建的槽并没有delete,会造成内存泄露,现实中还是别这么干,或者及时delete吧。
#include <cstdio>
#include <cstring> struct Point
{
int x,y;
bool operator<(const Point& cmp) const
{
return x==cmp.x?y<cmp.y:x<cmp.x;
}
} point[],p,q; struct Hash
{
int x,y;
Hash* next;
Hash()
{
next=;
}
} hash[]; inline int calHash(int x,int y)
{
return ((x<<)^y)&;
} void insert(int x,int y)
{
int h=calHash(x,y);
Hash* p=&hash[h];
while(p->next)
p=p->next;
p->x=x;
p->y=y;
p->next=new Hash();
} bool find(int x,int y)
{
int h=calHash(x,y);
Hash* p=&hash[h];
while(p->next)
{
if(p->x==x && p->y==y)
return true;
p=p->next;
}
return false;
} bool calK(Point& a,Point& b)
{
if(a.x==b.x)
return false;
if(a.y==b.y)
return true;
if(((a.x-b.x)&(<<))==((a.y-b.y)&(<<)))
return true;
return false;
} inline int Abs(int n)
{
return n<?-n:n;
} int main()
{
// freopen("in.txt","r",stdin);
int n;
while(~scanf("%d",&n) && n)
{
memset(hash,,sizeof(hash));
for(int i=;i<n;i++)
{
scanf("%d%d",&point[i].x,&point[i].y);
insert(point[i].x,point[i].y);
} int count=;
for(int i=;i<n;i++)
for(int k=i+;k<n;k++)
{
if(calK(point[i],point[k]))
{
int _y=Abs(point[i].y-point[k].y);
int _x=Abs(point[i].x-point[k].x);
if(find(point[i].x+_y,point[i].y-_x) &&
find(point[k].x+_y,point[k].y-_x))
count++;
}
}
printf("%d\n",count);
}
}
最简单的办法,set……1360MS
#include <cstdio>
#include <cstring>
#include <set>
using namespace std; struct Point
{
int x,y;
bool operator<(const Point& cmp) const
{
return x==cmp.x?y<cmp.y:x<cmp.x;
}
} point[],p,q; set<Point> ss; bool calK(Point& a,Point& b)
{
if(a.x==b.x)
return false;
if(a.y==b.y)
return true;
if(((a.x-b.x)&(<<))==((a.y-b.y)&(<<)))
return true;
return false;
} inline int Abs(int n)
{
return n<?-n:n;
} int main()
{
// freopen("in.txt","r",stdin);
int n;
while(~scanf("%d",&n) && n)
{
ss.clear();
for(int i=;i<n;i++)
{
scanf("%d%d",&point[i].x,&point[i].y);
ss.insert(point[i]);
} int count=;
for(int i=;i<n;i++)
for(int k=i+;k<n;k++)
{
if(calK(point[i],point[k]))
{
int _y=Abs(point[i].y-point[k].y);
int _x=Abs(point[i].x-point[k].x);
p.x=point[i].x+_y;
p.y=point[i].y-_x;
if(ss.find(p)==ss.end())
continue; p.x=point[k].x+_y;
p.y=point[k].y-_x;
if(ss.find(p)!=ss.end())
count++;
}
}
printf("%d\n",count);
}
}
三个版本是慢慢优化出来的,哈希函数也有区别。
POJ 2002 Squares 解题报告(哈希 开放寻址 & 链式)的更多相关文章
- poj 2002 Squares 几何二分 || 哈希
Squares Time Limit: 3500MS Memory Limit: 65536K Total Submissions: 15137 Accepted: 5749 Descript ...
- USACO Section1.2 Palindromic Squares 解题报告
palsquare解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------ ...
- POJ 2002 Squares【值得摸索的一道二分+点旋转】
id=2002">Squares 很好的一道二分,事实上本来我是没有思路的,看了基神的题解之后才似乎明确了点. 题意:给出最多有1000个点,问这些点能够组成多少个正方形 分析:先想想 ...
- java哈希表(线性探测哈希表。链式哈希表)
哈希表(散列表) 通过哈希函数使元素的存储位置与它 的关键码之间能够建立一一映射的关系,在查找时可以很快找到该元素. 哈希表hash table(key,value) 的做法其实很简单,就是把Key通 ...
- POJ 2002 Squares 哈希
题目链接: http://poj.org/problem?id=2002 #include <stdio.h> #include <string.h> ; struct Has ...
- POJ 1840 Eps 解题报告(哈希)
a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0,xi∈[-50,50],且xi!=0.让我们求所有解的可能. 首先,如果暴力判断的话,每个x的取值有100种可能,100^5肯定 ...
- 【原创】poj ----- 1182 食物链 解题报告
题目地址: http://poj.org/problem?id=1182 题目内容: 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submi ...
- POJ 2002 Squares 几何, 水题 难度: 0
题目 http://poj.org/problem?id=2002 题意 已知平面内有1000个点,所有点的坐标量级小于20000,求这些点能组成多少个不同的正方形. 思路 如图,将坐标按照升序排列后 ...
- poj 1201 Intervals 解题报告
Intervals Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu Submit Statu ...
随机推荐
- 08_rlCoachKin自主编译,调试
为了知道参数的意思,以及为了从头建立一个项目,我从使用QTCreator来单独建立项目(当然也可以直接使用源代码中建立好的VS项目). 其实也推荐 VS2010调试 如果是用自带的VS项目,那么我们需 ...
- A Case for Flash Memory SSD in Enterprise Database Applications
通过分析固态硬盘的特性对数据库中不同对象,如:表,索引,回滚段,重做日志等的应用进行具体研究,最后将数据库中不同的对象进行区别应用
- lucene 4.0学习
一:官方文件 http://lucene.apache.org/core/4_0_0/ ps:网上参考文章:http://www.cnblogs.com/xing901022/p/3933675.ht ...
- dynamic 动态获取object数据
1.替代XXX.GetType().GetProperty("YYY").GetValue(XXX) static object GetPerson() { return new ...
- memcached全面剖析--4
memcached的分布式算法 memcached的分布式 正如第1次中介绍的那样, memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能. 服务器端仅包括 第2次. 第 ...
- STL的pair学习, map学习
http://blog.csdn.net/calvin_zcx/article/details/6072286 http://www.linuxidc.com/Linux/2014-10/107621 ...
- Java学习--Equals与“==”
在Java规范中,它对equals()方法的使用必须要遵循如下几个规则: equals 方法在非空对象引用上实现相等关系: 1.自反性:对于任何非空引用值 x,x.equals(x) 都应返回 tru ...
- userInteractionEnabled
NO -------是自身View下面的按钮之类的能点 YES------是View自身的按钮能点击,他下面的不能点击
- VS2015下的Android开发系列01——开发环境配置及注意事项
概述 VS自2015把Xamarin集成进去后搞Android开发就爽了,不过这安装VS2015完成的时候却是长了不知道多少.废话少说进正题,VS2015安装时注意把Android相关的组件勾选安装, ...
- IOS 获得通讯录中联系人的所有属性 备用参考
ABAddressBookRef addressBook = ABAddressBookCreate(); CFArrayRef results = ABAddressBookCopyArrayOfA ...