题目链接:
http://poj.org/problem?id=1971
题意:
二维空间给n个任意三点不共线的坐标,问这些点能够组成多少个不同的平行四边形。
题解:
使用的平行四边形的判断条件:对角线互相平分的四边形是平行四边形。
所以我们枚举每一条线段,如果有两条线段的中点是重合的,那么这四个顶点就能构成一个平行四边形,也就是说每条线段我们只要维护中点就可以了。
1、map维护中点:(数据比较大,t了)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<map> 6 #include<utility> 7 using namespace std; 8 typedef long long LL; 9 10 const int maxn = 1111; 11 12 int n; 13 int x[maxn],y[maxn]; 14 map<pair<int,int>,int> mp; 15 16 void init(){ 17 mp.clear(); 18 } 19 20 int main(){ 21 int tc; 22 scanf("%d",&tc); 23 while(tc--){ 24 init(); 25 scanf("%d",&n); 26 for(int i=0;i<n;i++){ 27 scanf("%d%d",x+i,y+i); 28 } 29 int ans=0; 30 for(int i=0;i<n;i++){ 31 for(int j=i+1;j<n;j++){ 32 ans+=mp[make_pair(x[i]+x[j],y[i]+y[j])]; 33 mp[make_pair(x[i]+x[j],y[i]+y[j])]++; 34 } 35 } 36 printf("%d ",ans); 37 } 38 return 0; 39 }
2、用hash做(vector来建表)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<map> 6 #include<utility> 7 #include<vector> 8 using namespace std; 9 typedef long long LL; 10 11 const int maxn = 1111; 12 //可能是因为vector<int> tab[mod]的初始化影响很大 13 //1e3+7跑2985MS 1e4+7跑1282MS 1e5+7跑1750MS 1e6+7跑4532MS 14 const int mod = 1e3+7; 15 16 struct Point { 17 int x, y, cnt; 18 Point(int x, int y, int cnt = 0) :x(x), y(y), cnt(cnt) {} 19 Point() { cnt = 0; } 20 }pt[maxn]; 21 22 int n; 23 vector<Point> tab[mod]; 24 int Hash(const Point& p) { 25 //LL tmp = (p.x) *1000000007 + p.y; 26 int tmp = ((p.x << 2) + (p.x >> 4)) ^ (p.y << 10); //折叠法,比上面一个稍微快一点 27 //注意哈希出来的要是非负数 28 tmp = (tmp%mod + mod) % mod; 29 return tmp; 30 } 31 32 int add(const Point& p) { 33 int key = Hash(p); 34 int pos = -1; 35 for (int i = 0; i<tab[key].size(); i++) { 36 Point& tmp = tab[key][i]; 37 if (p.x == tmp.x&&p.y == tmp.y) { 38 pos = i; break; 39 } 40 } 41 int ret = 0; 42 if (pos == -1) { 43 tab[key].push_back(Point(p.x, p.y, 1)); 44 } 45 else { 46 ret = tab[key][pos].cnt; 47 tab[key][pos].cnt++; 48 } 49 return ret; 50 } 51 52 void init() { 53 for (int i = 0; i<mod; i++) tab[i].clear(); 54 } 55 56 int main() { 57 int tc; 58 scanf("%d", &tc); 59 while (tc--) { 60 init(); 61 scanf("%d", &n); 62 for (int i = 0; i<n; i++) { 63 scanf("%d%d", &pt[i].x, &pt[i].y); 64 } 65 int ans = 0; 66 for (int i = 0; i<n; i++) { 67 for (int j = i + 1; j<n; j++) { 68 Point p = Point(pt[i].x + pt[j].x, pt[i].y + pt[j].y); 69 ans += add(p); 70 } 71 } 72 printf("%d ", ans); 73 } 74 return 0; 75 }
3、用邻接表做散列表,初始化可以省一些时间 954MS
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<map> 6 #include<utility> 7 #include<vector> 8 using namespace std; 9 typedef long long LL; 10 11 const int maxn = 1111; 12 13 const int mod = 1e6+7; 14 15 struct Point { 16 int x, y, cnt, ne; 17 Point(int x, int y, int cnt = 0) :x(x), y(y), cnt(cnt) {} 18 Point(int x, int y, int cnt, int ne) :x(x), y(y), cnt(cnt), ne(ne) { } 19 Point() { cnt = 0; } 20 }pt[maxn],egs[maxn*maxn]; 21 22 int n; 23 int tab[mod],tot; 24 int Hash(const Point& p) { 25 LL tmp = (p.x) *1000000007 + p.y; 26 // int tmp = ((p.x << 2) + (p.x >> 4)) ^ (p.y << 10); //折叠法,比上面一个稍微快一点 27 //注意哈希出来的要是非负数 28 tmp = (tmp%mod + mod) % mod; 29 return tmp; 30 } 31 32 int add(const Point& p) { 33 int key = Hash(p); 34 int pos = -1,_p=tab[key]; 35 while (_p != -1) { 36 Point& e = egs[_p]; 37 if (p.x == e.x&&p.y == e.y) { 38 pos = _p; break; 39 } 40 _p = e.ne; 41 } 42 int ret = 0; 43 if (pos == -1) { 44 egs[tot] = Point(p.x, p.y, 1, tab[key]); 45 tab[key] = tot++; 46 } 47 else { 48 ret = egs[pos].cnt; 49 egs[pos].cnt++; 50 } 51 return ret; 52 } 53 54 void init() { 55 memset(tab, -1, sizeof(tab)); 56 tot = 0; 57 } 58 59 int main() { 60 int tc; 61 scanf("%d", &tc); 62 while (tc--) { 63 init(); 64 scanf("%d", &n); 65 for (int i = 0; i<n; i++) { 66 scanf("%d%d", &pt[i].x, &pt[i].y); 67 } 68 int ans = 0; 69 for (int i = 0; i<n; i++) { 70 for (int j = i + 1; j<n; j++) { 71 Point p = Point(pt[i].x + pt[j].x, pt[i].y + pt[j].y); 72 ans += add(p); 73 } 74 } 75 printf("%d ", ans); 76 } 77 return 0; 78 }