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 ...
随机推荐
- CSU-ACM2016暑期集训训练4-BFS(F - Oil Deposits)
F - Oil Deposits Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u De ...
- Poj 2159 / OpenJudge 2159 Ancient Cipher
1.链接地址: http://poj.org/problem?id=2159 http://bailian.openjudge.cn/practice/2159 2.题目: Ancient Ciphe ...
- bootstrap和jQuery.Gantt的css冲突问题
bootstrap是广泛使用的一个前端框架, 而jQuery.Gantt在目前也是一个很好用的用于绘制甘特图的插件. 这次在同时使用它们时,发现甘特图显示异常,如图 不加载bootstrap. ...
- POJ1182并查集
食物链 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描述 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物, ...
- Nodejs初学者福音
Nodejs+Express+MongoDb 搭建个人博客 001 我喜欢把任务或者工作分解成工作流来完成,如下,后面将会按照流程来详述,希望能为Nodejs初学者及推广Nodejs做出些努力. n ...
- Python基于比较的排序
排序是算法学习中最基本的问题. 1.平均时间复杂度均为O(N2)的排序 1.1 插入排序 插入排序对少量元素的排序非常有效.工作机制就像打牌一样,为了将牌插入到已排好序的牌中,需要将牌与手中的牌从右向 ...
- Oracle job procedure
Oracle job procedure 存储过程定时任务 oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务. 一.查询系统中的job,可以查询视图 --相关视图 ...
- win10应用安装位置修改方法
win10应用安装位置怎么改?很多用户升级win10的系统之后,对于win10应用装置的位置如何修改一直不知道如何解决,今天,小编就跟大家一起来看看如何修改win10应用装置的位置. win10应用安 ...
- 使用text-overflow:ellipsis对溢出文本显示省略号有两个好处
使用text-overflow:ellipsis对溢出文本显示省略号有两个好处,一是不用通过程序限定字数:二是有利于SEO.需要使用对对溢出文本显示省略号的通常是文章标题列表,这样处理对搜索引擎更友好 ...
- SecureCRT+WinSCP 共用 key pub 密钥 转换 ppk 登录ssh
使用SecureCRT生成的密钥,无法在WinSCP使用, 使用puttygen.exe无法直接转换,解决办法 1.使用大于等于SecureCRT6.5版本,来转换 记得放入私钥,不是pub公钥.然后 ...