经典好题。

题意是要我们找出所有的正方形。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 解题报告(哈希 开放寻址 & 链式)的更多相关文章

  1. poj 2002 Squares 几何二分 || 哈希

    Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 15137   Accepted: 5749 Descript ...

  2. USACO Section1.2 Palindromic Squares 解题报告

    palsquare解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------ ...

  3. POJ 2002 Squares【值得摸索的一道二分+点旋转】

    id=2002">Squares 很好的一道二分,事实上本来我是没有思路的,看了基神的题解之后才似乎明确了点. 题意:给出最多有1000个点,问这些点能够组成多少个正方形 分析:先想想 ...

  4. java哈希表(线性探测哈希表。链式哈希表)

    哈希表(散列表) 通过哈希函数使元素的存储位置与它 的关键码之间能够建立一一映射的关系,在查找时可以很快找到该元素. 哈希表hash table(key,value) 的做法其实很简单,就是把Key通 ...

  5. POJ 2002 Squares 哈希

    题目链接: http://poj.org/problem?id=2002 #include <stdio.h> #include <string.h> ; struct Has ...

  6. POJ 1840 Eps 解题报告(哈希)

    a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0,xi∈[-50,50],且xi!=0.让我们求所有解的可能. 首先,如果暴力判断的话,每个x的取值有100种可能,100^5肯定 ...

  7. 【原创】poj ----- 1182 食物链 解题报告

    题目地址: http://poj.org/problem?id=1182 题目内容: 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submi ...

  8. POJ 2002 Squares 几何, 水题 难度: 0

    题目 http://poj.org/problem?id=2002 题意 已知平面内有1000个点,所有点的坐标量级小于20000,求这些点能组成多少个不同的正方形. 思路 如图,将坐标按照升序排列后 ...

  9. poj 1201 Intervals 解题报告

    Intervals Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Submit Statu ...

随机推荐

  1. 新安装Eclipse后的一些配置

    配置护眼的背景色 Window-> Preferences-> General-> Editors-> Text Editors: Appearance color optio ...

  2. 17_高级映射:一对一查询(使用resultType)

    [数据库模型] [各个表] [ 用户表user ] 购买商品的用户信息. [ 订单表 ] 用户所创建的订单 [ 订单明细表 ] 订单的详细信息,即购买商品的信息 [ 商品表 ] 商品的具体信息 [有关 ...

  3. Oracle PL/SQL 找出100以内是3和5的倍数的数 循环语句

    循环: loop --执行代码 exit when 表达式;--当表达式为真退出循环.(注意,其编写位置决定循环为先判断还是先执行,相当于java的while或do-while) end loop; ...

  4. android开发之GenyMotion与intelliJ的配置

    (注意:这是在你的电脑上安装了intelliJ和安卓SDK后才进行的工作,如果没有intelliJ和安卓SDK,请先安装以上两样东西) 号称史上最快乐的模拟器GenyMotion,试一下. 第一步:下 ...

  5. javascripct字符串

    String 对象 String 对象用于处理文本(字符串). 创建 String 对象的语法: new String(s); String(s); 参数 参数 s 是要存储在 String 对象中或 ...

  6. ASP.NET 学习小记 -- “迷你”MVC实现(2)

    Controller的激活 ASP.NET MVC的URL路由系统通过注册的路由表对HTTO请求进行解析从而得到一个用户封装路由数据的RouteData对象,而这个过程是通过自定义的UrlRoutin ...

  7. C++ 输入输出文件流(ifstream&ofstream)

    ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间; 在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O, ...

  8. 树莓派 raspberry 入门之安装操作系统以及配置

    最近新入手一树莓派,型号是2代B,屏幕是微雪的7 inch c型 显示屏.下面来教大家怎么点亮树莓派. 第一步,装好显示器,显示器的电源接在树莓派的usb口上,HDMI口不多说,连上.然后装好鼠标.键 ...

  9. OAuth在WebApi中的使用,前后台分离的调用方式

    前段时间由于公司架构服务层向WebApi转换,就研究了OAuth在WebApi中的使用,这中间遇到了很多坑,在此记录一下OAuth的正确使用方式. 1.  OAuth是做什么的? 在网上浏览时,大家都 ...

  10. userInteractionEnabled

    NO -------是自身View下面的按钮之类的能点 YES------是View自身的按钮能点击,他下面的不能点击