(2017多校训练第二场)HDU - 6055 & POJ - 2002 Regular polygon 哈希
2017-07-31 16:44
465 查看
多校的这道题目因为输入的点的坐标都是整数,所以能够构成的正多边形只能是正方形。
所以问题就转化成了求输入的点能够构成多少个正方形。
枚举四个点肯定是会超时的,我们可以选择枚举两个点,然后用数学公式求出另外两个点的坐标,然后查找这两个求出来的坐标是不是存在的,如果存在就构成一个正方形。
还要注意同一个正方形会被枚举四遍,所以答案要除以4。
如何快速的查找一个点是不是存在呢,我们可以采用哈希的方法,哈希函数为平方取模,也就是(x^2+y^2)%mod,解决冲突采用链访法, 即用链表解决冲突。
如果一个正方形两个相邻点的坐标为(x1, y1),(x2, y2)
则另外两个点的坐标分别为
x3=x1+(y1-y2) y3= y1-(x1-x2)
x4=x2+(y1-y2) y4= y2-(x1-x2)
或
x3=x1-(y1-y2) y3= y1+(x1-x2)
x4=x2-(y1-y2) y4= y2+(x1-x2)
公式可以利用三角形全等推导出来(在正方形的外面补一个更大的正方形)
代码如下:
所以问题就转化成了求输入的点能够构成多少个正方形。
枚举四个点肯定是会超时的,我们可以选择枚举两个点,然后用数学公式求出另外两个点的坐标,然后查找这两个求出来的坐标是不是存在的,如果存在就构成一个正方形。
还要注意同一个正方形会被枚举四遍,所以答案要除以4。
如何快速的查找一个点是不是存在呢,我们可以采用哈希的方法,哈希函数为平方取模,也就是(x^2+y^2)%mod,解决冲突采用链访法, 即用链表解决冲突。
如果一个正方形两个相邻点的坐标为(x1, y1),(x2, y2)
则另外两个点的坐标分别为
x3=x1+(y1-y2) y3= y1-(x1-x2)
x4=x2+(y1-y2) y4= y2-(x1-x2)
或
x3=x1-(y1-y2) y3= y1+(x1-x2)
x4=x2-(y1-y2) y4= y2+(x1-x2)
公式可以利用三角形全等推导出来(在正方形的外面补一个更大的正方形)
代码如下:
#include <bits/stdc++.h> using namespace std; typedef long long int LL; const int MOD = 1999; const int MAX_N = 2000; struct Point { int x, y; Point* next; }; Point p[MAX_N]; Point* Hash[MAX_N]; void Insert(int x, int y) { int key = (x * x + y * y) % MOD; Point* head = Hash[key]; Point* tmp = new Point; tmp->x = x; tmp->y = y; tmp->next = 0; if (!head) Hash[key] = tmp; else { while (head->next) head = head->next; head->next = tmp; } } bool Find(int x, int y) { int key = (x * x + y * y) % MOD; Point* head = Hash[key]; while (head) { if (head->x == x && head->y == y) return true; head = head->next; } return false; } int main() { //freopen("test.txt", "r", stdin); //freopen("out.txt", "w", stdout); cin.sync_with_stdio(false); int n; while (cin >> n) { //if (!n) // break; memset(Hash, 0, sizeof(Hash)); for (int i = 1; i <= n; i++) { cin >> p[i].x >> p[i].y; Insert(p[i].x, p[i].y); } int ans = 0; for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) { int a = p[j].x - p[i].x; int b = p[j].y - p[i].y; int x3 = p[i].x + b; int y3 = p[i].y - a; int x4 = p[j].x + b; int y4 = p[j].y - a; if(Find(x3, y3) && Find(x4, y4)) ans++; x3 = p[i].x - b; y3 = p[i].y + a; x4 = p[j].x - b; y4 = p[j].y + a; if(Find(x3, y3) && Find(x4, y4)) ans++; } cout << ans / 4 << endl; } return 0; }
相关文章推荐
- 2017 多校训练第二场 HDU 6055 Regular polygon
- hdu 6055 : Regular polygon (2017 多校第二场 1011) 【计算几何】
- 2017多校联合第二场 1011题 hdu 6055 Regular polygon 计算几何
- HDU 2017 多校联合训练赛2 1011 6055 Regular polygon map&pair
- 【2017多校训练2+计算几何+板】HDU 6055 Regular polygon
- 2017 杭电多校联赛第二场 1011 Regular polygon(多个点求正方形个数)POJ 2002
- HDU 6180 && 2017 多校训练:Schedule
- HDU 6134 && 2017 多校训练:Battlestation Operational(莫比乌斯反演+积性函数)
- 2017 多校训练第二场 HDU 6053 TrickGCD
- (2017多校训练第二场)HDU - 6053 TrickGCD 初见莫比乌斯
- HDU 6162 && 2017 多校训练:Ch's gift(树链剖分)
- 2017 多校训练第二场 HDU 6050 Funny Function
- (2017多校训练第二场)HDU - 6047 Maximum Sequence 贪心 + 单调队列
- (2017多校训练第二场)HDU - 6052 To my boyfriend 思维题
- 2017 多校训练第二场 HDU 6047 Maximum Sequence
- 2017 多校训练第二场 HDU 6047 Maximum Sequence(贪心+优先队列)
- HDU 6055 (2017 多校训练赛2 1011)Regular polygon
- 2017 多校训练第二场 HDU 6045 Is Derek lying?
- HDU 6170 && 2017 多校训练:Two strings(DP)
- HDU 6166 && 2017 多校训练:Senior Pan(最短路)