您的位置:首页 > 其它

poj 2002 Squares (哈希+正方形已知相邻两点求另外两点的坐标)

2017-04-06 20:05 459 查看
题意: 给出n个坐标 , 问能组成多少个正方形

解法:  暴力解法=>直接枚举4个点 =》时间复杂度 O(n^4) => (1000)^4 =>10^12显然会T

          利用正方形的性质, 枚举两个点作为满足正方形条件的一条边AB,,

         即可推导出AB上方满足条件的边CD的坐标(C的坐标和D的坐标), 和 AB下方满足条件的 边C‘’D‘’的坐标(C‘’的坐标和D‘’的坐标);

       只要C和D(C''和D'')同时存在在给定的n个坐标中,那么这个正方形就是存在的 =>  sum++;

      由于, 每次枚举一条边, 那么, 一个正方形的四条边都会被枚举一次, 也就是说每个满足条件的正方形都被计算了4次, 所有得出的答案 = sum/4

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1e4+50;
int getHash(int x, int y){
int key = (abs(x*31+y*131))%maxn;
return key;
}
struct stars{
int x, y;
}s[maxn];
struct node{
int x, y;
node *next;
}Hash[maxn];
int vis[maxn];
int n;
void pushHash(int x, int y){
int key = getHash(x, y);
if(vis[key]){
node *p = new node;
p->x = x;
p->y = y;
p->next = NULL;
node *q = &Hash[key];
while(q->next){
q = q->next;
}
q->next = p;
} else {
Hash[key].x = x;
Hash[key].y = y;
Hash[key].next = NULL;
}
vis[key]=1;
return ;
}
bool cmp(stars a, stars b){
if(a.x != b.x) return a.x < b.x;
else return a.y<b.y;
}
bool find(int x, int y){
int key = getHash(x, y);
// cout <<"key "<< key <<endl;
if(!vis[key]) return false;
node *q = &Hash[key];
while(q){
if(q->x==x && q->y==y) return true;
q = q->next;
}
return false;
}
int main(){
//freopen("in.txt", "r", stdin);
int i,j, xc, xd, yc, yd;
while(~scanf("%d", &n)){
if(!n) break;
memset(vis, 0, sizeof(vis));
for(i=1; i<=n; i++){
scanf("%d %d", &s[i].x, &s[i].y);
pushHash(s[i].x, s[i].y);
}
int sum = 0;
//排序后才能确定枚举的坐标A在坐标B的左侧或者上方
//这样才能对应相应的公式推导出C, D坐标
sort(s+1, s+1+n, cmp);
for(i=1; i<=n; i++){ // 坐标A
for(j=i+1; j<=n; j++){//坐标B1
// cout <<"a : ("<<s[i].x<<","<<s[i].y<<")"<<endl;
// cout <<"b : ("<<s[j].x<<","<<s[j].y<<")"<<endl;
xc = s[i].x - (s[i].y - s[j].y);
yc = s[i].y + (s[i].x - s[j].x);
xd = s[j].x - (s[i].y - s[j].y);
yd = s[j].y + (s[i].x - s[j].x);
// cout <<"c : ("<<xc<<","<<yc<<")"<<endl;
// cout <<"d : ("<<xd<<","<<yd<<")"<<endl;
if(find(xc, yc) && find(xd, yd)) sum++
4000
;

/***********************************************/
xc = s[i].x + s[i].y - s[j].y;
yc = s[i].y - (s[i].x - s[j].x);
xd = s[j].x + s[i].y - s[j].y;
yd = s[j].y - (s[i].x - s[j].x);
if(find(xc, yc) && find(xd, yd)) sum++;
}
}
printf("%d\n", sum/4);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: