POJ 1971 Parallelogram Counting

题目链接:

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\n",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\n", 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\n", ans);
76     }
77     return 0;
78 }

 

posted @ 2016-05-01 01:25  fenicnn  阅读(426)  评论(0编辑  收藏  举报