poj 2002 哈希和二分
2013-03-08 10:48
429 查看
Squares
Description
A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a polygon such that rotating about its centre by 90 degrees gives the same polygon. It is not the only polygon with the latter property, however,
as a regular octagon also has this property.
So we all know what a square looks like, but can we find all possible squares that can be formed from a set of stars in a night sky? To make the problem easier, we will assume that the night sky is a 2-dimensional plane, and each star is specified by its x
and y coordinates.
Input
The input consists of a number of test cases. Each test case starts with the integer n (1 <= n <= 1000) indicating the number of points to follow. Each of the next n lines specify the x and y coordinates (two integers) of each point. You may assume that the
points are distinct and the magnitudes of the coordinates are less than 20000. The input is terminated when n = 0.
Output
For each test case, print on a line the number of squares one can form from the given stars.
Sample Input
Sample Output
Source
Rocky Mountain 2004
算法过程:
1 将顶点按x坐标递增排序,若x相同,按y坐标递增排序,然后枚举所有边,对每一条由点p1和p2(根据排序p1 < p2)组成的边按照如下方式可唯一确定一个正方形:
1) 将边绕p1逆时针旋转90度得到点p3
2) 将边绕p2顺时针旋转90度得到点p4
则p1 p2 p3 p4组成一个正方形,设p1 = (x1,y1), p2 = (x2, y2),根据向量的旋转公式可以求出p3, p4的坐标为
p3 = (y1 - y2 + x1, x2 - x1 + y1)
p4 = (y1 - y2 + x2, x2 - x1 + y2)
2 然后搜索点p3和p4是否存在,若存在则找到一个正方形,计数加1,可以发现总是存在两条边确定的正方形是一样的,也就是说每个正方形会被发现2次,所以要将最后的计数结果除以2.
实现的时候关键是如何搜索某个点是否存在,由于所有点都排序过,所以可以用二分查找来搜索,但速度比较慢,至少1000ms, hash的速度更快些,可以达到几百ms,还有hash表如果用开放地址线性探测法解决冲突的话,很容易超时,
而用链地址法解决冲突效果要好很多。下面是二分搜索和hash两种方法的代码实现。
二分查找:
哈希算法:
Time Limit: 3500MS | Memory Limit: 65536K | |
Total Submissions: 13153 | Accepted: 4870 |
A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a polygon such that rotating about its centre by 90 degrees gives the same polygon. It is not the only polygon with the latter property, however,
as a regular octagon also has this property.
So we all know what a square looks like, but can we find all possible squares that can be formed from a set of stars in a night sky? To make the problem easier, we will assume that the night sky is a 2-dimensional plane, and each star is specified by its x
and y coordinates.
Input
The input consists of a number of test cases. Each test case starts with the integer n (1 <= n <= 1000) indicating the number of points to follow. Each of the next n lines specify the x and y coordinates (two integers) of each point. You may assume that the
points are distinct and the magnitudes of the coordinates are less than 20000. The input is terminated when n = 0.
Output
For each test case, print on a line the number of squares one can form from the given stars.
Sample Input
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
Sample Output
1 6 1
Source
Rocky Mountain 2004
算法过程:
1 将顶点按x坐标递增排序,若x相同,按y坐标递增排序,然后枚举所有边,对每一条由点p1和p2(根据排序p1 < p2)组成的边按照如下方式可唯一确定一个正方形:
1) 将边绕p1逆时针旋转90度得到点p3
2) 将边绕p2顺时针旋转90度得到点p4
则p1 p2 p3 p4组成一个正方形,设p1 = (x1,y1), p2 = (x2, y2),根据向量的旋转公式可以求出p3, p4的坐标为
p3 = (y1 - y2 + x1, x2 - x1 + y1)
p4 = (y1 - y2 + x2, x2 - x1 + y2)
2 然后搜索点p3和p4是否存在,若存在则找到一个正方形,计数加1,可以发现总是存在两条边确定的正方形是一样的,也就是说每个正方形会被发现2次,所以要将最后的计数结果除以2.
实现的时候关键是如何搜索某个点是否存在,由于所有点都排序过,所以可以用二分查找来搜索,但速度比较慢,至少1000ms, hash的速度更快些,可以达到几百ms,还有hash表如果用开放地址线性探测法解决冲突的话,很容易超时,
而用链地址法解决冲突效果要好很多。下面是二分搜索和hash两种方法的代码实现。
二分查找:
#include <iostream> #include<stdio.h> #include<vector> using namespace std; int n;//节点数 int sumAll;//正方形总数 typedef struct node { int x,y; }node; node allNode[2000]; int cmp(const void *a,const void *b) { node x1=*((node*)a);node y1=*((node*)b); if (x1.x>y1.x) { return 1; } if (x1.x<y1.x) { return -1; } if (x1.x==y1.x&&x1.y>y1.y) { return 1; } if (x1.x==y1.x&&x1.y<y1.y) { return -1; } else return 0; } void init() { sumAll=0; int i; for(i=1;i<=n;i++) { scanf("%d%d",&allNode[i].x,&allNode[i].y); } qsort(&allNode[1],n,sizeof(allNode[1]),cmp); } bool finds(node x3) { int m, s, t; s = 1; t = n; while (s <= t) { m = (s+t)/2; if (allNode[m].x == x3.x && allNode[m].y == x3.y) return true; if (allNode[m].x > x3.x || (allNode[m].x == x3.x && allNode[m].y > x3.y)) { t = m-1; } else { s = m+1; } } return false; } bool query(node x1,node x2) { node x3,x4; if (((x1.x)+(x2.x)+(x1.y)-(x2.y))%2!=0) { return false; } x3.x=((x1.x)+(x2.x)+(x1.y)-(x2.y))/2; x3.y=((x1.y)+(x2.y)+(x2.x)-(x1.x))/2; x4.x=((x1.x)+(x2.x)-(x1.y)+(x2.y))/2; x4.y=((x1.y)+(x2.y)-(x2.x)+(x1.x))/2; if (finds(x3)&&finds(x4)) { return true; } return false; } void solve() { int i,j; for (i = 1; i <=n; i++) { for (j = i+1; j<=n; j++) { if(query(allNode[i],allNode[j])==true) { sumAll++; } } } } int main() { while(true) { cin>>n; if(n==0)break; init(); solve(); cout<<sumAll/2<<endl; } }
哈希算法:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__) #else #define debug(...) #endif #define N 1000 /* 顶点个数 */ #define M 2999 /* hash表的大小,取素数冲突冲突较少 */ struct Point { int x; int y; }; struct Point point ; /* 使用链地址法解决冲突, 表头不存数据 */ struct hash_entry { int x; int y; struct hash_entry *next; }; struct hash_entry hash_table[M+1]; int conflict; void insert(int x, int y) { unsigned int p; struct hash_entry *new_entry; p = (x*x+y*y)%M; /* hash函数 */ //创建一个新的entry new_entry = (struct hash_entry *)malloc(sizeof(struct hash_entry)); new_entry->x = x; new_entry->y = y; /* 把新entry插在最前面,这样,越先插进来的entry在链表的越后面, *最后一个entry的next指针为空 */ new_entry->next = hash_table[p].next; hash_table[p].next = new_entry; } int find(int x, int y) { unsigned int p; struct hash_entry *entry; p = (x*x+y*y)%M; /* hash函数 */ for(entry = hash_table[p].next; entry != 0 && (entry->x != x \ || entry->y != y); entry = entry->next, conflict++); if (entry) { return 1; } return 0; } int main() { int n, x, y, i, j, count; while (scanf("%d", &n), n) { memset(hash_table, 0, sizeof(hash_table)); count = 0; for (i = 0; i < n; i++) { scanf("%d %d", &x, &y); //插入法对点排序,按照x从小到大,y从小到大,且x优先排列的方式 for (j = i-1; j >= 0; j--) { if (point[j].x > x || (point[j].x == x && point[j].y > y)) { point[j+1] = point[j]; } else { break; } } point[j+1].x = x; point[j+1].y = y; insert(x, y); } /* 枚举所有边,对每条边的两个顶点可以 * 确定一个唯一的正方形,并求出另外两个顶点的坐标 */ for (i = 0; i < n; i++) { for (j = (i+1); j < n; j++) { //计算第三个点的坐标,搜索其是否存在 x = point[i].y-point[j].y+point[i].x; y = point[j].x-point[i].x+point[i].y; if (!find(x, y)) { continue; } //计算第四个点的坐标,搜索其是否存在 x = point[i].y-point[j].y+point[j].x; y = point[j].x-point[i].x+point[j].y; if (find(x, y)) { count++; } } } printf("%d\n", count/2); } debug("conflict = %d\n", conflict); return 0; }
相关文章推荐
- poj 2002 Squares 几何二分 || 哈希
- poj2002~对哈希表的理解进一步加深了
- POJ 2002 Squares 哈希
- POJ 2002 Squares(简单的二分)
- poj 2002 Squares 【stl二分】
- poj 2503 Babelfish(字典树或map或哈希或排序二分)
- POJ 2002 hash(枚举+哈希) 或者 枚举+二分
- POJ 2002 二分求解
- POJ 2002(hash||二分,数学)
- [poj 3261] Milk Patterns:二分,哈希或后缀数组
- POJ 2002 Squares【值得摸索的一道二分+点旋转】
- POJ 2002 哈希
- Poj 2002 Squares(二分&&STL)
- 【二分查找】-POJ-2002-Squares
- POJ 2002 Squares(几何 + 二分查找)
- POJ 2002 Squares 解题报告(哈希 开放寻址 & 链式)
- [POJ2002]Squares(计算几何,二分)
- poj_2002 Squares(哈希)
- poj 2002 Squares (哈希+正方形已知相邻两点求另外两点的坐标)
- POJ 2002 Squares 求正方形的个数,点哈希