POJ 2002 Squares 几何 + 二分搜索 或 hash

题目链接

题目大意:给你n个点 问能组成多少个不同的正方形  

思路:枚举2个点 由全等三角形得到另外2点坐标 二分查找这2个点是否存在


已知两个点,然后做出两个全等三角形。之后就得出结论(x1+|y1-y2|, y1+|x1-x2|),(x2+|y1-y2|,y2+|x1-x2|)。

二分查找法


#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1005;
const int inf = 1<<30;
int n,ans;
struct Node
{
	int x,y;
}point[maxn],c,d;
bool cmp( Node a,Node b )
{
	if( a.x == b.x )
		return a.y < b.y;
	else
		return a.x < b.x;
}
void getPoint( Node &a,Node &b )
{
	c.x = a.x + (a.y-b.y);
	c.y = a.y + (b.x-a.x);
	d.x = b.x + (a.y-b.y);
	d.y = b.y + (b.x-a.x);
}
bool find( Node s )
{
	int ld = 0,rd = n-1,mid;
	while( ld <= rd )
	{
		mid = (ld+rd)>>1;
		if( s.x == point[mid].x && s.y == point[mid].y )
			return true;
		if( s.x < point[mid].x || ( s.x == point[mid].x && s.y < point[mid].y ) )
			rd = mid-1;
		else
			ld = mid + 1;
	}
	return false;
}
void fun()
{
	for( int i = 0; i < n; i ++ ){
		for( int j = i+1; j < n; j ++ ){
			getPoint( point[i],point[j] );
			if( find(c) && find(d) )
				ans ++;
		}
	}
}
int main()
{
	//freopen("data.txt","r",stdin);
	while( scanf("%d",&n) != EOF,n )
	{
		for( int i = 0; i < n; i ++ )
		{
			scanf("%d%d",&point[i].x,&point[i].y);
		}
		sort( point,point+n,cmp );
		ans = 0;
		fun();
		printf("%d\n",ans/2);
	}
	return 0;
}

Hash

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1005;
const int inf = 1<<30;
int n,ans;
struct Node
{
	int x,y;
}point[maxn],c,d;
int Hash[maxn*40],Next[maxn];   //已点|x+y|为下标 hash用链接表形式解决冲突
bool cmp( Node a,Node b )
{
	if( a.x == b.x )
		return a.y < b.y;
	else
		return a.x < b.x;
}
void getPoint( Node &a,Node &b )
{
	c.x = a.x + (a.y-b.y);
	c.y = a.y + (b.x-a.x);
	d.x = b.x + (a.y-b.y);
	d.y = b.y + (b.x-a.x);
}
bool find( Node s )
{
	int key = abs( s.x + s.y );
	int k = Hash[key];
	while( k != -1 )
	{
		if( point[k].x == s.x && point[k].y == s.y )
			return true;
		k = Next[k];
	}
	return false;
}
void fun()
{
	for( int i = 0; i < n; i ++ ){
		for( int j = i+1; j < n; j ++ ){
			getPoint( point[i],point[j] );
			if( find(c) && find(d) )
					ans ++;
		}
	}
}
int main()
{
	//freopen("data.txt","r",stdin);
	while( scanf("%d",&n) != EOF,n )
	{
		for( int i = 0; i < n; i ++ )
			scanf("%d%d",&point[i].x,&point[i].y);
		sort( point,point+n,cmp );
		memset( Hash,-1,sizeof(Hash) );
		int key;
		for( int i = 0; i < n; i ++ )
		{
			key = abs( point[i].x + point[i].y );
			Next[i] = Hash[key];
			Hash[key] = i;
		}
		ans = 0;
		fun();
		printf("%d\n",ans/2);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值