poj 2002 -- hash

原创 2012年03月22日 20:22:22

题目:给你n个点,求能组成多少个正方形?

范围最大1000个点,时间3.5s,暴力枚举不用想肯定会超时。超时并不代表枚举行不通,实际上我们可以枚举两个点,然后在考虑下面的情况。

首先搞清楚两个问题,1、给你两个点,你能否求出用这两个点组成正方形一条边的其他两个点?2、如果给你一个点,你能否快速O(1)时间内告诉我这个点是否在给出的所有点当中。

 

如果你解决了上面两个问题,这个题目就好办了。

首先第一个问题,给你两个点,求正方形其他两个点坐标,注意,这里千万不要把这两个点当做对角线上的两个点,这样的话,你将会求不出正方形的个数。我们就以这两个点连成的线段当做正方形的一条边来做,不考虑对角线情况。

那么,给你正方形一条边,肯定有两种组成正方形的情况,关于这条边对称的肯定有两个正方形,还是给个图吧!

 

如以AB线段为边可以有1 2两个正方形。

如果A点坐标为x1,y1, B点x2,y2,可以求出两组(x3,y3)和(x4,y4)。

 

根据上图1三角形和2三角形全等周围的框都是平行于x轴和y轴的,很容易求得另外两个点的两组坐标

已知: (x1,y1)  (x2,y2)

则:   x3=x1+(y1-y2)   y3= y1-(x1-x2)

x4=x2+(y1-y2)   y4= y2-(x1-x2)

x3=x1-(y1-y2)   y3= y1+(x1-x2)

x4=x2-(y1-y2)   y4= y2+(x1-x2)

 

第二个问题,就是如果知道了C,D两个点如何判断这两个点是否在点集里面。

方法很多,可以用C++ STL,同时也可以用hash。

hash,有很多方法构造散列表,这里用平方求余法。关于hash方面的知识,这里就不介绍了。


下面就只剩下代码了:

#include <iostream>
using namespace std;

struct Node
{
	int x,y;
	Node * next;
}node[40001];

int n;
int cod[1005][2];
int Find(int x, int y)
{
	int key = (x * x + y * y) % 40001;
	Node *tmp = &node[key];
	while (tmp->next != NULL)
	{
		tmp = tmp->next;
		if (tmp->x == x && tmp->y == y)
		{
			return 1;
		}
	}
	return 0;
}
int main()
{
	while (scanf("%d", &n) && n)
	{
		memset(node, 0, sizeof(node));
		Node * point;
		for (int i = 1; i <= n; ++ i) 
		{
			point = new Node;
			scanf("%d %d", &cod[i][0], &cod[i][1]);
			point->x = cod[i][0];
			point->y = cod[i][1];
			point->next = NULL;

			int key = (cod[i][0] * cod[i][0] + cod[i][1] * cod[i][1]) % 40001;
			Node *tmp = &node[key];
			while (tmp->next != NULL)
			{
				tmp = tmp->next;
			}
			tmp->next = point;
		}

		int ans = 0;
		int x1,y1,x2,y2;
		for (int i = 1; i < n; ++ i)
		{
			for (int j = i + 1; j <= n; ++ j)
			{
				//two points on one side
				x1 = cod[i][0] + (cod[i][1] - cod[j][1]);
				y1 = cod[i][1] - (cod[i][0] - cod[j][0]);
				x2 = cod[j][0] + (cod[i][1] - cod[j][1]);
				y2 = cod[j][1] - (cod[i][0] - cod[j][0]);
				if (Find(x1,y1) && Find(x2,y2))
				{
					ans ++;
				}
				//
				x1 = cod[i][0] - (cod[i][1] - cod[j][1]);
				y1 = cod[i][1] + (cod[i][0] - cod[j][0]);
				x2 = cod[j][0] - (cod[i][1] - cod[j][1]);
				y2 = cod[j][1] + (cod[i][0] - cod[j][0]);
				if (Find(x1,y1) && Find(x2,y2))
				{
					ans ++;
				}
			}
		}
		printf("%d\n", ans / 4);
	}
	return 0;
}


 注意,最后求出的总数要除以4,为什么呢?比如一个正方形四个点顺时针依次是 1 2 3 4.那么我们枚举点的时候,肯定是1-2 1-3 1-4 2-3 2-4 3 -4,这里面可以有正方形的是1-2, 1-4, 2-3, 3-4所以重复了4遍。

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

POJ2002 正方形的个数(二维点的哈希)

给定N个点,求出这些点一共可以构成多少个正方形。 若正方形为ABCD,A坐标为(x1, y1),B坐标为(x2, y2),则很容易可以推出C和D的坐标。对于特定的A和B坐标,C和D可以在线段AB的左...
  • alongela
  • alongela
  • 2012年12月01日 23:11
  • 3480

POJ 2002 Squares (Hash)

题意:给你二维平面点集 让你找出其中能组成多少个正方形 思路:对每一个点进行哈希 枚举两个点做为正方形的一条边 然后再求另外两个点 看看原点集中是否存在这两个点 由于枚举的是每条边 则一个正方形会被...
  • s_h_r
  • s_h_r
  • 2015年06月16日 13:10
  • 244

POJ 2002 (hash)

Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 11096   Accep...
  • mad_lpx
  • mad_lpx
  • 2012年03月13日 20:06
  • 276

poj 2002 Squares Hash

Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 17327   Accep...
  • kimnoic
  • kimnoic
  • 2015年07月08日 22:52
  • 162

poj 2002 (hash map)

Squares Time Limit: 3500 MSMemory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java...
  • ilblue
  • ilblue
  • 2016年11月16日 20:13
  • 71

POJ 2002 Squares hash

Squares Time Limit:3500MS Memory Limit:65536KB 64bit IO Format:%lld & %llu SubmitStatus D...
  • Katapeltes
  • Katapeltes
  • 2016年08月09日 22:07
  • 138

poj 2002 Squares(hash)

意义给你n个点的坐标,问你可以围成多少个正方形。思路 可以得出 temp.x = p[i].x + (p[i].y - p[j].y); temp.y = p[i].y + (p[j].x - ...
  • qq872425710
  • qq872425710
  • 2016年12月12日 20:34
  • 117

POJ 2002 Squares -- Hash

Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 15891   Accep...
  • u010276926
  • u010276926
  • 2014年07月29日 10:56
  • 453

poj 2002 hash

找到两个点,算出组成正方形的另外两个点,如果都存在就true; 一直都是用这个n进制哈希方法,因为第一次遇见被它惊呆了。 1032ms #include #include #include ...
  • yeqm_
  • yeqm_
  • 2015年10月24日 20:10
  • 130

POJ 2002 Squares(hash)

Description 给出n个整点的坐标,问这n个点能组成多少个正方形 Input 多组用例,每组用例第一行为点数n,之后n行每行两个整数x和y表示该点坐标,以n=0结束输入(1 ...
  • V5ZSQ
  • V5ZSQ
  • 2015年12月28日 14:51
  • 287
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj 2002 -- hash
举报原因:
原因补充:

(最多只允许输入30个字)