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> 的初始化影响很大
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、用邻接表做散列表。

时间: 2024-11-19 16:58:21

POJ 1971 Parallelogram Counting的相关文章

【POJ】Parallelogram Counting(HASH,数学之平行四边形)

Parallelogram Counting 题意:输入t表示有t组数据 每组数据输入一个数n,表示有n个点 然后有n行,每行是这个点的(x,y) 问这些点能组成多少个平行四边形 思路:求中点,中点一样的是一个平行四边形. 记录同一个中点的个数sum(初始为1),平行四边形数是(sum-1) * sum / 2; #include<iostream> #include<algorithm> using namespace std; typedef long long ll; con

POJ 1791 Parallelogram Counting(求平行四边形数量)

Description There are n distinct points in the plane, given by their integer coordinates. Find the number of parallelograms whose vertices lie on these points. In other words, find the number of 4-element subsets of these points that can be written a

计算几何 + 统计 --- Parallelogram Counting

Parallelogram Counting Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5749   Accepted: 1934 Description There are n distinct points in the plane, given by their integer coordinates. Find the number of parallelograms whose vertices lie o

POJ 2386 Lake Counting 搜索题解

简单的深度搜索就可以了,看见有人说什么使用并查集,那简直是大算法小用了. 因为可以深搜而不用回溯,故此效率就是O(N*M)了. 技巧就是增加一个标志P,每次搜索到池塘,即有W字母,那么就认为搜索到一个池塘了,P值为真. 搜索过的池塘不要重复搜索,故此,每次走过的池塘都改成其他字母,如'@',或者'#',随便一个都可以. 然后8个方向搜索. #include <stdio.h> #include <vector> #include <string.h> #include

Parallelogram Counting(平行四边形个数,思维转化)

1058 - Parallelogram Counting    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB There are n distinct points in the plane, given by their integer coordinates. Find the number of parallelograms whose vertices lie on these po

POJ 2282 The Counting Problem,组合数学

POJ 2282 The Counting Problem,组合数学 ACM 题目地址:POJ 2282 题意: 给出俩数n,m,求从n~m中0~9分别出现的次数. 分析: 组合数学. 只要能快速算出0~n中各个数的出现次数就能解决问题了. 要把数拆开来看,比如3456=3000+400+50+6. 然后就只要考虑后面都是0的数就行了. 0~3000中,我们要分为两部分来考虑: 在第一位中,0\1\2都出现了1000次. 假设不管第一位,后面那些位数出现0~9的几率是均等的(先不考虑前导0).那

《挑战》2.1 POJ 2386 Lake Counting (简单的dfs)

1 # include<cstdio> 2 # include<iostream> 3 4 using namespace std; 5 6 # define MAX 123 7 8 char grid[MAX][MAX]; 9 int nxt[8][2] = { {1,0},{0,-1},{-1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1} }; 10 int n,m; 11 12 int can_move( int x,int y ) 13 { 14

POJ 1971 统计平行四边形 HASH

题目链接:http://poj.org/problem?id=1971 题意:给定n个坐标.问有多少种方法可以组成平行四边形.题目保证不会有4个点共线的情况. 思路:可以发现平行四边形的一个特点,就是对角线相交后得到的点.如果两点线的中点相交,那么这两条线就可以组成一个平行四边形[不需去排除4点共线],所以枚举两两组合的点对HASH成中点.然后判断所有中点,如果某个中点出现了K次,那么可以组成K*(K-1)/2个平行四边形. 用map来判断某个中点出现次数会TLE,所以可以对中点进行排序后判重复

poj 2386 Lake Counting

Lake Counting Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 24578   Accepted: 12407 Description Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 10