poj2002 squares 哈希 计算几何

题意,给出平面上n个点,求能形成的正方形个数

挺简单的题,用两个点来枚举。首先把所有的点用哈希函数处理后存起来,然后枚举两个点,以这两点为正方形同一边的两顶点,求出另外顶点的位置,然后查找这两个点是否存在即可。

这题用的静态链表做的,当成练习。同时注意下哈希函数,发同用x*x+y*y会TLE,毕竟也可能会有挺多相同的,然后为了区别x和y的正负性,把哈希函数改成x*x+y*y+x+y,我觉得这个答案一定不小于0的,所以没取绝对值,结果RE了。。。百思不得期解Orz

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXN 1005
#define PRIME 21911
#define SIZE 1500
typedef struct hashtable{
	int x, y;
	int next;
}Hashtable;
Hashtable hashlist[SIZE];
int avail;
int hashs[PRIME+5];
void init(){
	avail=1;
	memset(hashs, -1, sizeof(hashs));
}
int getnode(){
	int p;
	p=avail;avail++;
	return p;
}
void insert(int p, int x, int y){
	hashlist[p].x=x;hashlist[p].y=y;
	hashlist[p].next=-1;
}
int hashf(int x, int y){
	int ret;
	ret=x*x+y*y+x+y;
	ret*=31;
	if(ret<0)ret=-ret;
	ret%=PRIME;
	return ret;
}
void update(int key, int x, int y){
	if(hashs[key]==-1){
		hashs[key]=getnode();
		insert(hashs[key], x, y);
	}
	else{
		int pos=hashs[key];
		while(hashlist[pos].next!=-1){
			pos=hashlist[pos].next;
		}
		int cur=getnode();
		hashlist[pos].next=cur;
		insert(cur, x, y);
	}
}
bool isthesame(Hashtable a, int x, int y){
	if(a.x==x&&a.y==y)return true;
	else return false;
}
bool isexist(int x, int y){
	int key=hashf(x, y);
	if(hashs[key]==-1)return false;
	int pos=hashs[key];
	while(hashlist[pos].next!=-1){
		if(isthesame(hashlist[pos], x, y))
			return true;
		pos=hashlist[pos].next;
	}
	if(isthesame(hashlist[pos], x, y))
		return true;
	return false;
}
struct node{
	int x, y;
	void in(int a, int b){
		x=a;y=b;
	}
}coor[MAXN];
int main(){
	int n;
	int x, y;
	while(scanf("%d", &n), n){
		init();
		for(int i=0;i<n;i++){
			scanf("%d%d", &x, &y);
			coor[i].in(x, y);
			update(hashf(x, y), x, y);
		}
		int xa, ya, xb, yb;
		int xt, yt;
		int ans=0;
		for(int i=0;i<n;i++){
			for(int j=i+1;j<n;j++){
				xt=coor[i].x-coor[j].x;
				yt=coor[i].y-coor[j].y;

				xa=coor[i].x+yt;ya=coor[i].y-xt;
				xb=coor[j].x+yt;yb=coor[j].y-xt;
				if(isexist(xa, ya)&&isexist(xb, yb))ans++;

				xa=coor[i].x-yt;ya=coor[i].y+xt;
				xb=coor[j].x-yt;yb=coor[j].y+xt;
				if(isexist(xa, ya)&&isexist(xb, yb))ans++;
			}
		}
		ans>>=2;
		cout<<ans<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值