poj2002 poj3432 正方形个数 (hash,二分)

给出一堆点,求其中正方形的个数。

题目很简单,如果枚举,复杂度为O(n^4),肯定超时,我们利用hash,或者二分来降低复杂度,枚举其中的两个点,然后利用正方形的性质求出其余的两个点,然后判断这两个点是否都存在,如果存在,说明可以组成一个正方形。判断的方式利用hash或者二分都可以,这个题目用的hash,poj3432用的二分。下面的问题就是给出两个点,如何求出其余的两个顶点。

给出两个点(a1,a2),(b1,b2),我们得到其余两个顶点为(a1+(b2-a2),a2-(b1-a1)),(b1+(b2-a2),b2-(b1-a1)),或者
(a1-(b2-a2), a2+(b1-a1)),( b1-(b2-a2), b2+(b1-a1)),我们只考虑一种情况就可以了,否则也是重复计算。这样对于同一个
正方形,每条边都计算了一遍(顶点已经排序),只是我们只计算每条边对应的左上方或者右下方的矩形,这样只有两条边对应的计算了一次,因此
需要将计数/2。

poj2002

代码:

View Code
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int N=1010;
const int M=40010;
struct m_point{
int x,y;
};
m_point s[N];
int m_hash[M],next[N],n;
bool cmp(const m_point &p1,const m_point &p2)
{
if(p1.x < p2.x)
return true;
if((p1.x == p2.x) && (p1.y < p2.y))
return true;
return false;
}
bool isExist(int x,int y)
{
int value=abs(x+y);
int index=m_hash[value];
while(-1 != index)
{
if((s[index].x == x) && (s[index].y == y))
return true;
index=next[index];
}
return false;
}
int main()
{
int i,j,value,new_x,new_y,ans=0;
m_point tmp;
while(scanf("%d",&n) && n)
{
ans=0;
memset(next,-1,sizeof(next));
memset(m_hash,-1,sizeof(m_hash));
for(i=0;i<n;++i)
scanf("%d%d",&s[i].x,&s[i].y);
sort(s,s+n,cmp);
for(i=0;i<n;++i)
{
 //hash函数是采用的两个坐标的和,和相同的用类似与链表连接起来
value=abs(s[i].x+s[i].y);
next[i]=m_hash[value];//技巧和图的邻接表存储方式相同
m_hash[value]=i;
}
// for(i=0;i<n;++i)
// cout<<s[i].x<<" "<<s[i].y<<'\t';
// cout<<endl;
for(i=0;i<n;++i)
{
for(j=i+1;j<n;++j)
{
tmp.x=s[j].x-s[i].x;
tmp.y=s[j].y-s[i].y;
new_x=s[i].x+tmp.y;
new_y=s[i].y-tmp.x;
if(!isExist(new_x,new_y))
continue;
new_x=s[j].x+tmp.y;
new_y=s[j].y-tmp.x;
if(!isExist(new_x,new_y))
continue;
++ans;
}
}
printf("%d\n",ans/2);
}
return 0;
}

poj3432

代码:

View Code
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int N=2002;
struct m_point{
int x,y;
};
int n;
m_point p[N];
bool cmp(const m_point &p1,const m_point &p2)
{
if(p1.x < p2.x)
return true;
if((p1.x == p2.x) && (p1.y < p2.y))
return true;
return false;
}
bool find_point(m_point &t)
{
int left=0,right=n,mid;
while(left<=right)
{
mid=(left+right)>>1;
if((p[mid].x == t.x) && (p[mid].y == t.y))
return true;
if(cmp(t,p[mid]))
right=mid-1;
else
left=mid+1;
}
return false;
}

int main()
{
int i,j,ans;
m_point tmp,new_node;
while(scanf("%d",&n) != EOF)
{
for(i=0;i<n;++i)
scanf("%d%d",&p[i].x,&p[i].y);
sort(p,p+n,cmp);
ans=0;
for(i=0;i<n;++i)
{
for(j=i+1;j<n;++j)
{
tmp.x=p[j].x-p[i].x;
tmp.y=p[j].y-p[i].y;
new_node.x=p[i].x+tmp.y;
new_node.y=p[i].y-tmp.x;
if(!find_point(new_node))
continue;
new_node.x=p[j].x+tmp.y;
new_node.y=p[j].y-tmp.x;
if(!find_point(new_node))
continue;
++ans;
}
}
printf("%d\n",ans/2);
}
return 0;
}



posted on 2011-12-03 16:58  buptLizer  阅读(1088)  评论(0编辑  收藏  举报

导航