题意描述:有一堆平面散点集,任取四个点,求能组成正方形的不同组合方式有多少。相同的四个点,不同顺序构成的正方形视为同一正方形。

思路变迁

1、最简单的方法,直接暴力搜索,即依次取四个顶点,根据其坐标判断是否能组成正方形。组成正方形的条件是四个顶点可组成的六条边里面,有四条相等,剩下两条相等。当然由于其时间复杂度为O(n^4),所以提交结果为TLE

2、考虑降低时间复杂度。如任取三个顶点,根据组成正方形的条件计算得到第四个顶点,判断其是否在点的集合内,其复杂度为O(n^3)。或者任取两个顶点,根据组成正方形的条件计算出另外两个顶点,再判断其是否在点的集合内,其复杂度为O(n^2)。

3、不论是任取两个顶点还是任取三个顶点,其关键一步都是判断计算得到的新的点,是否在点的集合内,基本方法有对点排序再二分查找,或者是使用hash表。我的设计是考虑点所处象限的二维hash表。根据这道题的提交结果来看,所用时间上,堆排序优于快排

4、对于任选两个顶点时,可能存在三种不同的正方形。但是在对所有顶点排序后,如若按序来去顶点,则可发现我们只需始终计算一个方向的即可,且计算结果中同一个正方形重复了两次,所以最终结果除以二。如若不排序直接任取两个的顶点的话,始终按一个方向计算,可以发现每个正方形的四条边,每一条边都会贡献一次得到的正方形的个数,所以最终结果需要除以四

5、在使用hash表后时间复杂度达到最优,即O(nlgn) + hash表平均冲突*n(n-1)/2,所以本问题的进一步优化,取决于怎么更大程度的降低hash表的冲突?考虑位运算,来存储所有的点,但需要空间太大,因为共有40000*40000个点

暴力搜索代码

 #include<stdio.h>
#define SIZE 1005
typedef struct POINT {
int x;
int y;
} point;
int isSquare(int a, int b, int c, int d);
point p[SIZE];
int main() {
int n, result;
int i, j, k, x;
scanf("%d", &n);
while(n != ) {
result = ;
for(i=; i<=n; i++)
scanf("%d %d", &p[i].x, &p[i].y);
for(i=; i<=n; i++) {
for(j=i+; j<=n; j++) {
for(k=j+; k<=n; k++) {
for(x=k+; x<=n; x++) {
if(isSquare(i, j, k, x))
result++;
}
}
}
}
printf("%d\n", result);
scanf("%d", &n);
}
} int isSquare(int a, int b, int c, int d) {
int s[];
int num1 = , num2 = ;
int side1 = -, side2 = -;
int i;
s[] = (p[a].x - p[b].x)*(p[a].x - p[b].x) + (p[a].y - p[b].y)*(p[a].y - p[b].y);
s[] = (p[a].x - p[c].x)*(p[a].x - p[c].x) + (p[a].y - p[c].y)*(p[a].y - p[c].y);
s[] = (p[a].x - p[d].x)*(p[a].x - p[d].x) + (p[a].y - p[d].y)*(p[a].y - p[d].y);
s[] = (p[b].x - p[c].x)*(p[b].x - p[c].x) + (p[b].y - p[c].y)*(p[b].y - p[c].y);
s[] = (p[b].x - p[d].x)*(p[b].x - p[d].x) + (p[b].y - p[d].y)*(p[b].y - p[d].y);
s[] = (p[c].x - p[d].x)*(p[c].x - p[d].x) + (p[c].y - p[d].y)*(p[c].y - p[d].y);
for(i=; i<=; i++) {
if(i == ) {
side1 = s[i];
}
else if(s[i] != side1) {
if(side2 == -)
side2 = s[i];
else if(s[i] == side2)
num2++;
else
break;
}
else if(s[i] == side1)
num1++;
}
if((num1== && num2==) || (num1== && num2 == ))
return ;
else
return ;
}

使用堆排序+二分查找代码

 #include<stdio.h>
#define SIZE 1005
typedef struct POiNT {
int x;
int y;
} point;
int cmp(point pa, point pb);
void heapSort(int n);
int binarySearch(int low, int high, point key);
void shiftDown(int i, int n);
void swap(int i, int j);
point p[SIZE];
int main() {
int n, result;
int i, j, k, x;
point pa, pb;
scanf("%d", &n);
while(n != ) {
result = ;
for(i=; i<=n; i++)
scanf("%d %d", &p[i].x, &p[i].y);
heapSort(n);
for(i=; i<=n; i++)
printf("%d %d\n", p[i].x, p[i].y); for(i=; i<=n; i++) {
for(j=i+; j<=n; j++) {
pa.x = p[i].x - (p[j].y - p[i].y);
pa.y = p[i].y + (p[j].x - p[i].x);
pb.x = pa.x + (p[j].x - p[i].x);
pb.y = pa.y + (p[j].y - p[i].y);
if(binarySearch(, n, pa) && binarySearch(, n, pb))
result++;
}
}
printf("%d\n", result/);
scanf("%d", &n);
}
}
int binarySearch(int low, int high, point key) {
int mid = (low + high)/;
if(low > high)
return ;
if(cmp(p[mid], key) == )
return ;
else if(cmp(p[mid], key) == )
return binarySearch(low, mid-, key);
else
return binarySearch(mid+, high, key);
}
void heapSort(int n) {
int i = n/;
for(; i>; --i)
shiftDown(i, n);
for(i=n; i>;) {
swap(, i);
shiftDown(, --i);
}
}
void shiftDown(int i, int n) {
int j = *i;
for(; j<=n; j=*i) {
if(j < n && cmp(p[j], p[j+]) == -)
j = j + ;
if(cmp(p[i], p[j]) == -) {
swap(i, j);
i = j;
} else
break;
}
}
void swap(int i, int j) {
point temp = p[i];
p[i] = p[j];
p[j] = temp;
}
int cmp(point pa, point pb) {
if(pa.x > pb.x)
return ;
else if(pa.x == pb.x && pa.y > pb.y)
return ;
else if(pa.x == pb.x && pa.y == pb.y)
return ;
else
return -;
}

考虑象限的hash代码

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 1013
typedef struct POiNT {
int x;
int y;
} point;
struct hashNode {
point poi;
struct hashNode *next;
};
int cmp(const void *a, const void *b );
void add(point key);
int find(point);
point p[SIZE];
struct hashNode hashTable[][SIZE];
int main() {
int n, result;
int i, j, k, x;
point pa, pb;
scanf("%d", &n);
while(n != ) {
result = ;
memset(hashTable, , sizeof(hashTable));
for(i=; i<=n; i++) {
scanf("%d %d", &p[i].x, &p[i].y);
add(p[i]);
}
qsort(p+, n, sizeof(p[]), cmp);
for(i=; i<=n; i++) {
for(j=i+; j<=n; j++) {
pa.x = p[i].x - (p[j].y - p[i].y);
pa.y = p[i].y + (p[j].x - p[i].x);
pb.x = pa.x + (p[j].x - p[i].x);
pb.y = pa.y + (p[j].y - p[i].y);
if(find(pa) && find(pb))
result++;
}
}
printf("%d\n", result/);
scanf("%d", &n);
}
}
void add(point key) {
int t, num;
struct hashNode *newNode;
if(key.x >= && key.y >= )
t = ;
else if(key.x >= && key.y < )
t = ;
else if(key.x < && key.y < )
t = ;
else
t = ;
num = (key.x*key.x + key.y*key.y)%SIZE;
newNode = (struct hashNode*)malloc(sizeof(struct hashNode));
newNode->poi = key;
newNode->next = hashTable[t][num].next;
hashTable[t][num].next = newNode;
}
int find(point key) {
int t, num;
struct hashNode *node;
if(key.x >= && key.y >= )
t = ;
else if(key.x >= && key.y < )
t = ;
else if(key.x < && key.y < )
t = ;
else
t = ;
num = (key.x*key.x + key.y*key.y)%SIZE;
node = hashTable[t][num].next;
while(node) {
if(node->poi.x == key.x && node->poi.y == key.y)
return ;
node = node->next;
}
return ;
}
int cmp(const void *a, const void *b )
{
point c = *(point*)a;
point d = *(point*)b; if(c.x == d.x)
return c.y - d.y;
else
return c.x - d.x;
}

Poj2002 Squares的更多相关文章

  1. poj2002 Squares(hash+折半枚举)

    Description A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-d ...

  2. POJ-2002 Squares,哈希模板+数学公式!

                                                           Squares 题意:二维坐标轴给出n个点求有多少个正方形. 要是平时做比赛的话毫无疑问会 ...

  3. [POJ2002]Squares(计算几何,二分)

    题目链接:http://poj.org/problem?id=2002 给定一堆点,求这些点里哪些点可以构成正方形,题目给定n<=1000,直接枚举四个点是肯定会超时的,因此要做一些优化. 有公 ...

  4. POJ2002 Squares(枚举)

    题目链接. 分析: 普遍的做法是:先枚举两个点,通过数学公式得到另外2个点,使得这四个点能够成正方形.然后检查散点集中是否存在计算出来的那两个点,若存在,说明有一个正方形. 但这种做法会使同一个正方形 ...

  5. poj2002 hash+邻接表优化Squares

    Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 17487   Accepted: 6643 Descript ...

  6. [poj2002]Squares_hash

    Squares poj-2002 题目大意:在笛卡尔坐标系中给出n个点,求这些点可以构成多少个正方形. 注释:$1\le n\le 10^3$,$-2\cdot 10^3\le x , y\le 2\ ...

  7. [LeetCode] Word Squares 单词平方

    Given a set of words (without duplicates), find all word squares you can build from them. A sequence ...

  8. 卡通图像变形算法(Moving Least Squares)附源码

    本文介绍一种利用移动最小二乘法来实现图像变形的方法,该方法由用户指定图像中的控制点,并通过拖拽控制点来驱动图像变形.假设p为原图像中控制点的位置,q为拖拽后控制点的位置,我们利用移动最小二乘法来为原图 ...

  9. Leetcode: Word Squares && Summary: Another Important Implementation of Trie(Retrieve all the words with a given Prefix)

    Given a set of words (without duplicates), find all word squares you can build from them. A sequence ...

随机推荐

  1. DVB系统中PCR的生成和PCR校正

    http://blog.csdn.net/chenliangming/article/details/3616720 引自<广播电视信息>2008年1月 从数字电视前端系统功能上来讲,传统 ...

  2. 利用CCProxy管理小型企业的上网行为

    本实验以实例方式,从操作条件.背景.需求.以及具体要求的几个部分进行说明. 1. 操作条件: 装有Windows Server 2003系统,安装了代理服务程序的虚拟机一台 2. 背景: 为了提高员工 ...

  3. Cygwin安装时,选择163的源后出错:Unable to get setup.ini from <http://mirrors.163.com/cygwin/>

    [问题] 折腾: [记录]Cygwin下把make从v3.82换成v3.81 期间,选择了163的源,结果出错: Cygwin Setup Unable to get setup.ini from & ...

  4. Hadoop初步认识

    Hadoop的介绍: Hadoop是一个适用于大数据的并行存储和计算的平台,是 Apache的一个用java 语言实现开源软件框架,实现了在大量计算机组成的集群中对海量数据进行分布式计算.Hadoop ...

  5. P132、面试题21:包含min函数的栈

    实现思路:们需要一个辅助栈.每次push一个新元素的时候,同时将最小元素(或最小元素的位置.考虑到栈元素的类型可能是复杂的数据结构,用最小元素的位置将能减少空间消耗)push到辅助栈中:每次pop一个 ...

  6. Oracle命令(一):Oracle登录命令

    1.运行SQLPLUS工具 C:\Users\wd-pc>sqlplus 2.直接进入SQLPLUS命令提示符 C:\Users\wd-pc>sqlplus /nolog 3.以OS身份连 ...

  7. Windows Embedded Compact 2013 安装体验

    6月14日,微软正式发布了Windows embedded compact 2013,大家还是习惯称之为Window CE 8,公司也要开始做windows embedded compact 2013 ...

  8. Android开发之内容观察者

    内容观察者: 当关注应用的数据库数据改变时,内容提供者会发出通知,在内容提供者的uri上注册一个内容观察者,就可以收到数据改变的通知 实现步骤: 1.假如是自定义的ContentProvider,需要 ...

  9. hdu4745Two Rabbits(dp)

    链接 哎..比赛中一下想到了公共子序 之后思维就被局限了 一直在这附近徘徊 想着怎么优化 怎么预处理.. 观看了众多神牛的代码 ..以前觉得自己能写出个记忆化的最长回文长度 还挺高兴的...现在觉得好 ...

  10. freemarker 如何获得list的索引值

    <#list toplist as toplists> ${toplists_index} </#list> 相当方便