Poj 1971 Parallelogram Counting (数据结构_Hash)

题目链接:http://poj.org/problem?id=1971


题目大意:给定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原创,但可以转载,因为我们是兄弟。

你可能感兴趣的:(数据结构,c,struct,测试)