NOI 3.5 哈希 1807:正方形

题目来源:

http://noi.openjudge.cn/ch0305/1807/

http://poj.org/problem?id=2002

 

1807:正方形

总时间限制8000ms    单个测试点时间限制4000ms   内存限制65536kB

描述

给出平面上一些点的坐标,统计由这些点可以组成多少个正方形。注意:正方形的边不一定平行于坐标轴。

输入

输入包括多组测试数据。每组的第一行是一个整数n (1 <= n <= 1000),表示平面上点的数目,接下来n行,每行包括两个整数,分别给出一个点在平面上的x坐标和y坐标。输入保证:平面上点的位置是两两不同的,而且坐标的绝对值都不大于20000。最后一组输入数据中n = 0,这组数据表示输入的结束,不用进行处理。

输出

对每组输入数据,输出一行,表示这些点能够组成的正方形的数目。

样例输入

4
1 0
0 1
1 1
0 0
9
0 0
1 0
2 0
0 2
1 2
2 2
0 1
1 1
2 1
4
-2 5
3 7
0 0
5 2
0

样例输出

1
6
1

来源

翻译自RockyMountain 2004的试题

 -----------------------------------------------------

思路

将输入的点存在数组和map中,数组是为了顺序遍历,map是为了查找快(O(logN)). 取正方形对角线上的两个顶点,根据简单的几何关系计算另外一条对角线上两个顶点,若计算出的另外两个顶点都在map中,则找到一个正方形。因为两条对角线各被计算了一次,因此结果要除以2.

特别注意的是已知对角线AC上的a, c坐标,求b点坐标的公式为

bx = (ax+cx+cy-ay)/2

by = (ay+cy+ax-cx)/2

由于所有坐标都是int存储的,所以如果(ax+cx+cy-ay)(ay+cy+ax-cx)不是2的倍数,bx,by也可能计算出在map中的值。所以要首先判断(ax+cx+cy-ay)和(ay+cy+ax-cx)是不是2的倍数,如果是2的倍数才可能和map中的其他点构成正方形

然后就是C++里的map是用红黑树实现的,查询的复杂度为O(logN). NOI上能过,在POJ上会TIMELIMIT EXCEED. 为了进一步降低查询的复杂度,需要用hash map hash map查询复杂度近似O(1). 可以用C++自己写hashmap,例如博文NOI 3.5 哈希 1551: Sumsets,偷懒的做法是用Java中的HashSet. 当然其实也挺麻烦的,因为节点类node要重写hashCodeequals方法,而且Java本身跑得慢,在POJ上也只是可以压着时间线过。

-----------------------------------------------------

代码

 C++版_map实现

#include
#include
#include
using namespace std;

struct node {
	int x,y;

	bool operator < (const node &b) const				// map用<来构建红黑树
	{
		if (x==b.x)
		{
			return y mp;
node vec[NMAX] = {};

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin ("0305_1807.txt");
	int i,j,ans=0;
	int x1,x2,x3,y1,y2,y3,x4,y4;
	node nd,nd1;
	while (fin >> n)
	{
		if (n==0)
		{
			break;
		}
		mp.clear();
		for (i=0; i> nd.x >> nd.y;
			vec[i] = nd;
			mp[nd] = 1;
		}
		ans = 0;
		for (i=0; i> n)
	{
		if (n==0)
		{
			break;
		}
		mp.clear();
		for (i=0; i> nd.x >> nd.y;
			vec[i] = nd;
			mp[nd] = 1;
		}
		ans = 0;
		for (i=0; i

Java版_HashSet实现

import java.util.HashSet;
import java.util.Scanner;
import java.util.Vector;

public class Main {
	public static Vector vec = new Vector();
	public static HashSet hm = new HashSet();
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int i,j,n,ans;
		Scanner sc = new Scanner(System.in);
		int xx,yy,x1,x2,x3,x4,y1,y2,y3,y4;
		while (true)
		{
			n=sc.nextInt();
			if (n==0)
			{
				break;
			}
			vec.clear();
			hm.clear();
			for (i=0; i

你可能感兴趣的:(百练OJ/poj,基础算法,NOI)