题目来源:

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要重写hashCode和equals方法,而且Java本身跑得慢,在POJ上也只是可以压着时间线过。

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

代码

 C++版_map实现

#include<iostream>
#include<fstream>
#include<map>
using namespace std;struct node {int x,y;bool operator < (const node &b) const               // map用<来构建红黑树{if (x==b.x){return y<b.y;}else{return x<b.x;}}
};const int NMAX = 1005;
const double EFS = 1e-5;
int n;
map<node, bool> mp;
node vec[NMAX] = {};int main()
{
#ifndef ONLINE_JUDGEifstream 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<n; i++){fin >> nd.x >> nd.y;vec[i] = nd;mp[nd] = 1;}ans = 0;for (i=0; i<n-1; i++){for (j=i+1; j<n; j++){x1 = vec[i].x;x2 = vec[j].x;y1 = vec[i].y;y2 = vec[j].y;if ((x1+x2+y2-y1)%2==0 && (y1+y2+x1-x2)%2==0 && (x1+x2+y1-y2)%2==0 && (y1+y2+x2-x1)%2==0){x3 = (x1+x2+y2-y1)/2;y3 = (y1+y2+x1-x2)/2;nd.x = x3;nd.y = y3;x4 = (x1+x2+y1-y2)/2;y4 = (y1+y2+x2-x1)/2;nd1.x = x4;nd1.y = y4;if (mp[nd] && mp[nd1]){ans++;}}}}ans /= 2;cout << ans << endl;}fin.close();
#endif
#ifdef ONLINE_JUDGEint i,j,ans=0;int x1,x2,x3,y1,y2,y3,x4,y4;node nd,nd1;while (cin >> n){if (n==0){break;}mp.clear();for (i=0; i<n; i++){cin >> nd.x >> nd.y;vec[i] = nd;mp[nd] = 1;}ans = 0;for (i=0; i<n-1; i++){for (j=i+1; j<n; j++){x1 = vec[i].x;x2 = vec[j].x;y1 = vec[i].y;y2 = vec[j].y;if ((x1+x2+y2-y1)%2==0 && (y1+y2+x1-x2)%2==0 && (x1+x2+y1-y2)%2==0 && (y1+y2+x2-x1)%2==0){x3 = (x1+x2+y2-y1)/2;y3 = (y1+y2+x1-x2)/2;nd.x = x3;nd.y = y3;x4 = (x1+x2+y1-y2)/2;y4 = (y1+y2+x2-x1)/2;nd1.x = x4;nd1.y = y4;if (mp[nd] && mp[nd1]){ans++;}}}}ans /= 2;cout << ans << endl;}
#endif
}

Java版_HashSet实现

import java.util.HashSet;
import java.util.Scanner;
import java.util.Vector;public class Main {public static Vector<node> vec = new Vector<node>();public static HashSet<node> hm = new HashSet<node>();/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubint 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<n; i++){xx = sc.nextInt();yy = sc.nextInt();node nd = new node(xx,yy);vec.add(nd);hm.add(nd);}ans = 0;for (i=0; i<n-1; i++){for (j=i+1; j<n; j++){x1 = vec.get(i).x;x2 = vec.get(j).x;y1 = vec.get(i).y;y2 = vec.get(j).y;if ((x1+x2+y2-y1)%2==0 && (y1+y2+x1-x2)%2==0 && (x1+x2+y1-y2)%2==0 && (y1+y2+x2-x1)%2==0){x3 = (x1+x2+y2-y1)/2;y3 = (y1+y2+x1-x2)/2;node nd1 = new node(x3,y3);x4 = (x1+x2+y1-y2)/2;y4 = (y1+y2+x2-x1)/2;node nd2 = new node(x4,y4);if (hm.contains(nd1) && hm.contains(nd2)){ans++;}}}}ans /= 2;System.out.println(ans);}}
}class node {public Integer x,y;public node(int xx, int yy){x = xx;y = yy;}/*** 为了使用HashSet, 需要重写hashCode和equals方法*/public boolean equals(Object obj){if (this == obj)return true;if (obj == null)return false;if(getClass() != obj.getClass())return false;node other = (node)obj;if(!x.equals(other.x))return false;if(!y.equals(other.y))return false;return true;}public int hashCode(){int res = 1;res = 31*res + x;res = 31*res + y;return res;}
}

NOI 3.5 哈希 1807:正方形相关推荐

  1. 信息学奥赛一本通 1056:点和正方形的关系 | OpenJudge NOI 1.4 18

    [题目链接] ybt 1056:点和正方形的关系 OpenJudge NOI 1.4 18:点和正方形的关系 [题目考点] 1. 逻辑表达式 [题解代码] 解法1:使用if-else #include ...

  2. 【NOI OJ】一大波题正在飞来(ˉ▽ ̄~) 我才不是 Ctrl C + Ctrl V 的人呢

    OpenJudge 登入 注册 管理员 frank 林舒 Dzx someone 李文新 公告 11-05 程序设计与算法(大学先修课) 成员(61647)查看全部 NOI(题库正在建设中,做题纪录有 ...

  3. 投入OJ的怀抱~~~~~~~~~~

    OpenJudge C20182024 信箱(1) 账号 修改设定 退出小组 管理员 frank 林舒 Dzx someone 李文新 公告 11-05 程序设计与算法(大学先修课) 成员(61910 ...

  4. 投入OJ的怀抱~~~

    OpenJudge 登入 注册 管理员 frank 林舒 Dzx someone 李文新 公告 11-05 程序设计与算法(大学先修课) 成员(85168)查看全部 NOI(题库正在建设中,做题纪录有 ...

  5. P4398 [JSOI2008]Blue Mary的战役地图

    知识点:二分,前缀和,哈希 难度:5 这个题一开始没有用二分,写了二分之后这个题就过了,由于才刚刚入门算法竞赛,知识储备比较有限,只能用我会的知识来写这道题,首先看这个题显然有单调性,可以使用二分,把 ...

  6. POJ - 2002 Squares 数正方形【二分】【哈希表】

    Squares POJ - 2002 题意 平面上有N个点,任取4个点,求能组成正方形的不同组合方式有多少种:相同的四个点,不同顺序构成的正方形视为同一正方形 分析 做法1 先枚举两个点,通过计算得到 ...

  7. noi题库1011. 正方形

    noi题库1011. 正方形 题目描述 有一个正方形,四个角的坐标分别是(1,-1),(1,1),(-1,-1),(-1,1).写一个程序,判断一个给定的点(x,y)是否在这个正方形内(包括正方形边界 ...

  8. 正方形个数(二维点哈希)

    题目:http://poj.org/problem?id=2002 题意:平面上给定n个点,求由这些点能构成多少个正方形. 分析:我们枚举两个点,那么在这两个点形成的直线两边可以计算出正方形的另外两个 ...

  9. P2601 [ZJOI2009]对称的正方形(二维哈希)(二分)

    洛谷传送门 文章目录 题目描述 解析 代码 题目描述 解析 做三个hash 分一下正方形边长的奇偶性 然后枚举中心点,二分边长即可 有点类似模拟赛那道红十字的题 我一开始觉得分奇偶好麻烦啊 为什么不直 ...

最新文章

  1. 画架构图的软件_程序员为什么要学会画技术架构图?
  2. Wince 中如何实现注册表恢复原厂设置
  3. LOJ #2733 [JOI2016春季合宿]Sandwiches (DP)
  4. 《Java 核心技术卷1 第10版》学习笔记------ final 关键字详解
  5. 基于MapReduce的贝叶斯网络算法研究参考文献
  6. 这是哪里来的小妖精!!!
  7. 调用SMS腾讯云短信验证码API的几个坑,及详细使用流程
  8. 程序员面试题100题第28题——全排列
  9. 定义项目名称快速启动项目
  10. 编写脚本常用的几种语句
  11. 2021 年 GitHub 最佳开源软件榜单
  12. GB28181标准文档以及GB35114标准文档免费下载
  13. 股票自动交易软件API使用流程
  14. telnet相似命令 linux,Linux telnet命令
  15. “数据科学”课程群与 “数据科学导论”课程建设初探
  16. html颜色渐变配色方案,css网站推荐 渐变色配色方案 - 小俊学习网
  17. MindSpore新工具TinyMS体验
  18. Word文档 | 删除回车符
  19. 零基础看得懂的C语言入门教程
  20. 苹果G5机箱改造 (螺帽法)

热门文章

  1. checkSession:fail 系统错误,错误码:-13001,session time out, need relogin
  2. Linux系统磁盘管理总结
  3. QT中setLayout无效的问题
  4. 分分钟让你理解HTTPS
  5. 31_Js根据13位时间戳转yyyy-MM-dd字符串
  6. Bootstrap中的面板(panel)
  7. python attrib判断字段是否存在操作
  8. joinquant量化是什么?
  9. Caffe 实例笔记 1 CaffeNet从训练到分类及可视化参数特征 微调
  10. 用python做一个文本情绪分析程序