经典好题。

题意是要我们找出所有的正方形。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. 06_XML的写入_dom4j添加、删除、修改Xml文件内容

    [工程截图] [person.xml]准备一个xml文件 <?xml version="1.0" encoding="UTF-8"?> <st ...

  2. 《jQuery UI开发指南》勘误收集

    此书由罗晴明 (http://weibo.com/sunnylqm)和我合译完成,此篇博客作为勘误收集而用,若译文有误或者有任何疑问,欢迎留下评论,或者给我发邮件(地址:gzooler@gmail.c ...

  3. iOS之多线程浅谈

    1)并发和并行的区别 在软件开发中不可避免的会遇到多线程的问题,在iOS客户端开发(或者.NET的winform或者wpf这样的cs程序)中就更不可避免的会用到多线程,在bs类型的web项目中要考虑一 ...

  4. rhel_6.x 安装mysql

    不知为何mysql的官网很难下载,本人网上找了好久,终于找到了个镜像: 特别感谢http://mirrors.sohu.com/mysql/MySQL-5.6/    ^_^ 首先下载mysql的下面 ...

  5. 51nod1242 斐波那契数列 矩阵快速幂

    1242 斐波那契数列的第N项 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 #include<stdio.h> #define mod 100000000 ...

  6. 51nod1057 N的阶乘

    输入N求N的阶乘的准确值.   Input 输入N(1 <= N <= 10000) Output 输出N的阶乘 Input示例 5 Output示例 120参考博客:blog.csdn. ...

  7. PHP字符

    匹配查找 strstr strpos 通常用在表单验证里面可以用到 substr 正值表达式匹配 preg_mathc(), preg)mathc_all() , preg_grep() 编码格式的转 ...

  8. Python+Bottle+Sina SAE快速构建网站

    Bottle是新生一代Python框架的代表,利用Bottle构建网站将十分简单. Sina SAE是国内较出名的云平台之一,十分适用于个人网站的开发或创业公司网站开发. 下面将介绍如果通过Pytho ...

  9. WPF中的一些常用类型转换

    1.string和Color的转换: //string转Color (Color)ColorConverter.ConvertFromString((string)str); //Color转stri ...

  10. Codeforces Round #344 (Div. 2) C. Report

    Report 题意:给长度为n的序列,操作次数为m:n and m (1 ≤ n, m ≤ 200 000) ,操作分为t r,当t = 1时表示将[1,r]序列按非递减排序,t = 2时表示将序列[ ...