POJ 2002 hash(枚举+哈希) 或者 枚举+二分
2009-10-06 20:33
513 查看
(zz)简单hash,具体做法是枚举任意两个点,因为有这由两个点所构成的边属于某个正方形那么可以计算出属于该正方形的另外两个点。如有两个点(a1,a2)和(b1,b2),那么如果点(a1+(a2-b2), a2-(a1-b1))和点(b1+(a2-b2), b2-(a1-b1))都存在则这四个点可以构成一个正方形。同时如果点(a1-(a2-b2), a2+(a1-b1))和点(b1-(a2-b2), b2+(a1-b1))存在那么点(a1,a2),(b1,b2),(a1-(a2-b2), a2+(a1-b1))和(b1-(a2-b2), b2+(a1-b1))又可以构成一个正方形,差不多思想就是这个样子,不过好像时间比较长1500多ms,应该还可以优化。
下面是AC代码:
#include<iostream>
using namespace std;
struct point
{
point()
{
index=-1;
next=NULL;
}
point(int index,point* next)
{
this->index=index;
this->next=next;
}
int index;
point* next;
};
int a[1001][2];
bool find(point hash_table[],int,int);
int main()
{
int n,value;
while(scanf("%d",&n)&&n)
{
long result=0;
point hash_table[40001];
for(int e=0;e<n;e++)
{
scanf("%d%d",&a[e][0],&a[e][1]);
value=a[e][0]+a[e][1];
if(value<0)value=-value;
if(hash_table[value].index==-1)hash_table[value].index=e;
else
{
point* p=&hash_table[value];
while(p->next!=NULL)p=p->next;
p->next=new point(e,NULL);
}
}
for(int x=0;x<n;x++)
for(int y=x+1;y<n;y++)
{
int d_x=a[x][0]-a[y][0];
int d_y=a[x][1]-a[y][1];
if(find(hash_table,a[x][0]-d_y,a[x][1]+d_x)&&
find(hash_table,a[y][0]-d_y,a[y][1]+d_x))
result++;
if(find(hash_table,a[x][0]+d_y,a[x][1]-d_x)&&
find(hash_table,a[y][0]+d_y,a[y][1]-d_x))
result++;
}
printf("%ld/n",result/4);
}
return 0;
}
bool find(point hash_table[40001],int x,int y)
{
int value=(x+y)<0?-(x+y):(x+y);
point* p=&hash_table[value];
if(p->index==-1)return false;
while(p!=NULL)
{
if(a[p->index][0]==x&&a[p->index][1]==y)return true;
p=p->next;
}
return false;
}
自己WA代码:
枚举+二分代码
枚举+hash代码
下面是AC代码:
#include<iostream>
using namespace std;
struct point
{
point()
{
index=-1;
next=NULL;
}
point(int index,point* next)
{
this->index=index;
this->next=next;
}
int index;
point* next;
};
int a[1001][2];
bool find(point hash_table[],int,int);
int main()
{
int n,value;
while(scanf("%d",&n)&&n)
{
long result=0;
point hash_table[40001];
for(int e=0;e<n;e++)
{
scanf("%d%d",&a[e][0],&a[e][1]);
value=a[e][0]+a[e][1];
if(value<0)value=-value;
if(hash_table[value].index==-1)hash_table[value].index=e;
else
{
point* p=&hash_table[value];
while(p->next!=NULL)p=p->next;
p->next=new point(e,NULL);
}
}
for(int x=0;x<n;x++)
for(int y=x+1;y<n;y++)
{
int d_x=a[x][0]-a[y][0];
int d_y=a[x][1]-a[y][1];
if(find(hash_table,a[x][0]-d_y,a[x][1]+d_x)&&
find(hash_table,a[y][0]-d_y,a[y][1]+d_x))
result++;
if(find(hash_table,a[x][0]+d_y,a[x][1]-d_x)&&
find(hash_table,a[y][0]+d_y,a[y][1]-d_x))
result++;
}
printf("%ld/n",result/4);
}
return 0;
}
bool find(point hash_table[40001],int x,int y)
{
int value=(x+y)<0?-(x+y):(x+y);
point* p=&hash_table[value];
if(p->index==-1)return false;
while(p!=NULL)
{
if(a[p->index][0]==x&&a[p->index][1]==y)return true;
p=p->next;
}
return false;
}
自己WA代码:
枚举+二分代码
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; struct Point { int x; int y; bool operator==(const Point & p) { return x==p.x && y==p.y; } bool operator<(const Point & p) { return x<p.x ||( x==p.x && y<p.y); } }p[1005]; int num=0; int cmp(const void * t1,const void *t2) { Point *p1 = (Point *)t1; Point *p2 = (Point*)t2; return *p2<*p1; } bool bin_search(Point *p,int s,int e,Point k) { int m; int l,h; l = s; h=e; while(l<=h) { m = l+(h-l)/2; if(k==p[m]) { return true; } else if(k<p[m]) { h=m-1; } else l=m+1; } return false; } void enumerate(int n) { int i ,j; for(i=0;i<n;i++) for(j=i+1;j<n;j++)//从最左边开始选边,然后枚举后面所有可能和当前边构成正方形的边 { int x1 = p[i].x; int y1 = p[i].y; int x2 = p[j].x; int y2 = p[j].y; if(y1==y2) continue; Point t3,t4; int tmp = abs(y1-y2); t3.x= x1+tmp; t4.x=x2 + tmp; if(y1>y2) { t3.y = y1+(x2-x1); t4.y = y2+(x2-x1);// } else if(y1 <y2) { t3.y = y1-(x2-x1); t4.y = y2-(x2-x1);// } if(bin_search(p,j+1,n-1,t3)==true && bin_search(p,j+1,n-1,t4)==true) num++; } } int main() { int n ; int i = 0; cin>>n; while(n!=0) { num=0; memset(p,0,sizeof(p)); for(i=0;i<n;i++) { cin>>p[i].x; cin>>p[i].y; p[i].x=p[i].x; p[i].y=p[i].y; } qsort(p,n,sizeof(struct Point),cmp); enumerate(n);//枚举 cout<<num<<endl; cin>>n; } }
枚举+hash代码
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; struct Point { int x; int y; bool operator==(const Point & p) { return x==p.x && y==p.y; } Point *next; }p[1005]; Point *hash[20000]; const int P = 19977; int num=0; int cmp(const void * t1,const void *t2) { Point *p2 = (Point *)t1; Point *p1 = (Point*)t2; if(p1->x < p2->x) return 1; else if(p1->x == p2->x) if(p1->y < p2->y) return 1; else return -1; return -1; } bool find(Point p) { int key = p.x+p.y; Point *n = hash[key%P]; while(n) { if(*n==p) return true; n=n->next; } return false; } void insert(Point p) { int key = p.x+p.y; Point * m = new Point; m->x=p.x; m->y=p.y; m->next=hash[key%P]; hash[key%P]=m; } void solve(int n) { int i = 0; int j = 0; for(i=0;i<n;i++) for(j=i+1;j<n;j++)//从最左边开始选边,然后枚举后面所有可能和当前边构成正方形的边 { int x1 = p[i].x; int y1 = p[i].y; int x2 = p[j].x; int y2 = p[j].y; Point t3,t4; t3.x= x1+(y1-y2); t3.y = y1-(x1-x2); t4.x = x2+(y1-y2); t4.y= y2-(x1-x2); if(find(t3) && find(t4)) num++; t3.x= x1-(y1-y2); t3.y = y1+(x1-x2); t4.x = x2-(y1-y2); t4.y= y2+(x1-x2); if(find(t3) && find(t4)) num++; } } int main() { int n ; int i = 0; cin>>n; while(n!=0) { num=0; memset(p,0,sizeof(p)); for(i=0;i<20000;i++) { hash[i]=NULL; } for(i=0;i<n;i++) { cin>>p[i].x; cin>>p[i].y; insert(p[i]); } qsort(p,n,sizeof(Point),cmp); solve(n); cout<<num/4<<endl; cin>>n; } }
相关文章推荐
- 【POJ】2002 - Squares(暴力枚举 & 双关键字二分查找)
- POJ 2002(hash||二分,数学)
- 二分|hash(找正方形)poj2002
- poj 2002 Squares(枚举+点hash)
- POJ 2002 Squares(计算几何 找正方形 hash枚举)
- poj 2785 二分或者hash
- POJ 2002 Squares 几何 + 二分搜索 或 hash
- pku 2002 Squares 二分查找 或者 hash
- poj 2785 求4个数相加和为0 的个数 hash 或者二分
- poj 3977 折半枚举二分搜索
- POJ 2289——Jamie's Contact Groups——————【多重匹配、二分枚举匹配次数】
- poj 2002 Squares(hash)
- HDU 1407 测试你是否和LTC水平一样高 枚举、二分、hash
- POJ 2002 Squares(二分)
- poj 3882(Stammering Aliens) 后缀数组 或者 hash
- poj2002 数正方形 hash
- POJ 2002 Squares【值得摸索的一道二分+点旋转】
- POJ 3977 Subset (折半枚举+二分)
- poj 2002 哈希和二分
- poj 2922 Honeymoon Hike(二分+dfs+区间枚举)