您的位置:首页 > 其它

POJ2002《Squares》方法:哈希

2013-04-01 10:40 134 查看
题目大意:给定平面上的一些坐标点(1000个),找出这些点能构成多少个正方形,坐标取值不大于20000。

解题思路:若遍历4个点的坐标,肯定超时。因此先取两个点坐标,然后用哈希值查找正方形的另两个点坐标,key = (x*x+y*y)%prime,这里prime取1999(不大于2n的素数),并用链地址法解决地址冲突。因为每个正方形按不同顺序被枚举了4次,所以要除以4。

// 620k 1360ms
#include <iostream>
#include <cstring>

using namespace std;

const int prime = 1999;

typedef class Node {
public:
	int x, y;
} Node;

Node node[1000];

typedef class HashTable {
public:
	int x, y;
	HashTable *next;
	HashTable()
	{
		next = NULL;
	}
} HashTable;

HashTable *hashs[prime];

void insert_hash(int x, int y)
{
	int key = (x*x + y*y) % prime;
	if (!hashs[key]) {
		HashTable *temp = new HashTable;
		temp->x = x;
		temp->y = y;
		hashs[key] = temp;
	} else {
		HashTable *temp = hashs[key];
		while (temp->next) {
			temp = temp->next;
		}
		temp->next = new HashTable;
		temp->next->x = x;
		temp->next->y = y;
	}
}

bool find(int x, int y)
{
	int key = (x*x + y*y) %prime;
	if (!hashs[key]) {
		return false;
	} else {
		HashTable *temp = hashs[key];
		while (temp) {
			if (temp->x == x && temp->y == y) {
				return true;
			}
			temp = temp->next;
		}
	}
	return false;
}

int main()
{
	//freopen("temp.txt", "r", stdin);
	int n, num;
	while (cin >> n && n != 0) {
		memset(hashs, 0, sizeof(hashs));
		num = 0;
		for (int i = 0; i < n; ++i) {
			cin >> node[i].x >> node[i].y;
			insert_hash(node[i].x, node[i].y);
		}
		int x1, x2, x3, x4, y1, y2, y3, y4, a, b;
		for (int i = 0; i < n-1; ++i) {
			for (int j = i+1; j < n; ++j) {
				x1 = node[i].x;
				y1 = node[i].y;
				x2 = node[j].x;
				y2 = node[j].y;
				a = x1 - x2;
				b = y1 - y2;
				x3 = x1 + b;
				y3 = y1 - a;
				x4 = x2 + b;
				y4 = y2 - a;
				if (find(x3, y3) && find(x4, y4)) {
					++num;
				}
				x3 = x1 - b;
				y3 = y1 + a;
				x4 = x2 - b;
				y4 = y2 + a;
				if (find(x3, y3) && find(x4, y4)) {
					++num;
				}
			}
		}
		cout << num/4 << endl;
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: