题目链接:http://poj.org/problem?id=1971
测试数据:
10
3
1000000000 -1000000000
0 0
-1000000000 1000000000
4
0 0
1 1
0 1
1 0
4
0 2
0 3
0 4
0 5
8
0 0
0 1
1 0
1 1
2 0
2 1
3 0
3 1
7
-2 -1
8 9
5 7
1 1
4 8
2 0
9 8
6
0 0
2 0
4 0
1 1
3 1
5 1
题目大意:给定n个点的坐标,问组成平行四边形的个数。
解题思路:若两条线段相互平分,那么他们可以做为平行四边形的对角线。既然是相互平分,也就是说两条线段的中点相同,他们可以确定一个平行四边形。这样本题就有两种解法:一、将每个中点排序,然后统计相同中点的个数N,答案Ans += C(N,2),因为会有重复,所以要用组合公式。二、用Hash保存每个中点,同一个中点映射到同一个地方。这里可以全部求出来以后按方法一那样求,也可以在发现和前面的某些中点一样时加上前面出现的中点数量,因为它可以喝前面那么多条线段组成平行四边形。我用的是第二种方法,因为练习Hash应用。第一种方法很简单,时间也会少些。
测试数据:
10
3
1000000000 -1000000000
0 0
-1000000000 1000000000
4
0 0
1 1
0 1
1 0
4
0 2
0 3
0 4
0 5
8
0 0
0 1
1 0
1 1
2 0
2 1
3 0
3 1
7
-2 -1
8 9
5 7
1 1
4 8
2 0
9 8
6
0 0
2 0
4 0
1 1
3 1
5 1
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define MAX 1100
#define INF 1000001
struct node {
int x,y,next,cnt;
}arr[INF],ver[MAX*2];
int ans,n,hash,head[INF];
int absx,absy,abslen,ptr;
int GetHash(int sum) {
int key = abs(sum) % INF;
return key % INF;
}
void CountAns(int i,int j) {
absx = ver[i].x + ver[j].x;
absy = ver[i].y + ver[j].y;
int key = GetHash(absx+absy);
hash = head[key];
while (hash){
if (arr[hash].y == absy && absx == arr[hash].x) {
ans += arr[hash].cnt,arr[hash].cnt++;
return;
}
hash = arr[hash].next;
}
arr[ptr].x = absx;
arr[ptr].y = absy;
arr[ptr].cnt = 1;
arr[ptr].next = head[key];
head[key] = ptr++;
}
int main()
{
int i,j,k,t;
scanf("%d",&t);
while (t--) {
scanf("%d",&n);
for (i = 0; i < n; ++i)
scanf("%d%d",&ver[i].x,&ver[i].y);
ans = 0,ptr = 1;
memset(head,0,sizeof(head));
for (i = 0; i < n; ++i)
for (j = 0; j < i; ++j)
CountAns(i,j);
printf("%d\n",ans);
}
}
本文ZeroClock原创,但可以转载,因为我们是兄弟。