POJ 1971 Parallelogram Counting (思维)

Parallelogram Counting

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 6969   Accepted: 2446

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 as {A, B, C, D} such that AB || CD, and BC || AD. No four points are in a straight line.

Input

The first line of the input contains a single integer t (1 <= t <= 10), the number of test cases. It is followed by the input data for each test case. 
The first line of each test case contains an integer n (1 <= n <= 1000). Each of the next n lines, contains 2 space-separated integers x and y (the coordinates of a point) with magnitude (absolute value) of no more than 1000000000. 

Output

Output should contain t lines. 
Line i contains an integer showing the number of the parallelograms as described above for test case i. 

Sample Input

2
6
0 0
2 0
4 0
1 1
3 1
5 1
7
-2 -1
8 9
5 7
1 1
4 8
2 0
9 8

Sample Output

5
6

Source

Tehran Sharif 2004 Preliminary

题意:

给你二维平面上n(n<=1e3)个点的坐标,保证没有四线共点,让你求可以组成的平行四边形的个数。

思路:

没有四线共点,言外之意就是有三线共点。(样例也给出了)

确定一个平行四边形,我们可以用多种方法,但是本题的复杂度要求在O(n*n)之内,也就是说我们只能记录每条边的信息,因此我们采用对边平行且相等来确定平行四边形。

我们对于任意两个点,可以求出它们的斜率(不存在设为inf)和距离。

我们显然只能枚举一个条件来判断另一个。

在纸上画画不难发现,在没有四点共线的情况下,n个点的完全图长度相同的边的数量很少。

于是我们把相同长度的边分组,每组暴力找有多少对斜率相同的边即可。

由于我们没有确定找的是平行四边形的上边还是下边,所以最后答案要除以2。

注意内存限制的比较紧,数组开到5e5即可。

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
const int maxn=1005;
const ll mo=1000000007;
const double eps=1e-12;
ll n,m,k;
struct node
{
	ll v;
	double x;
	int id;
	bool operator<(node aa) const
	{
		return v<aa.v;
	}
}hs[maxn*maxn>>1];
ll x[maxn],y[maxn];
ll tmp,cnt,ans;
struct nd
{
	int a,b;
	double xl;
}c[maxn];
ll cc;
ll power(ll a,ll n)   //a的n次方mod
{
    ll ans=1;
    a=a%mo;
    while (n)
    {
        if(n&1) ans=(ans*a)%mo;
        n>>=1;
        a=(a*a)%mo;
    }
    return ans;
}
double cal(int i,int j)
{
	if(x[i]==x[j]) return inf;
	return (double)(y[i]-y[j])/(double)(x[i]-x[j]);
}
ll cal2(int i,int j)
{
	return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&n);
        cnt=0;
        rep(i,1,n)
        {
        	scanf("%lld%lld",&x[i],&y[i]);
        	rep(j,1,i-1)
        	{
        		hs[cnt].v=cal2(i,j);
        		hs[cnt].x=cal(i,j);
        		hs[cnt].id=i*n+j;
        		cnt++;
			}
		}
        sort(hs,hs+cnt);
        int ct=0;
        ll ans=0;
        rep(i,0,cnt-1)
        {
        	if(i==0||hs[i].v!=hs[i-1].v)
        	{
				cc=0;
				c[cc].xl=hs[i].x;
				c[cc].a=hs[i].id/n;
				c[cc].b=hs[i].id%n;
				cc++;
			}
        	else
			{
				c[cc].xl=hs[i].x;
				c[cc].a=hs[i].id/n;
				c[cc].b=hs[i].id%n;
				//cc++;
				rep(j,0,cc-1)
				if(c[j].xl==c[cc].xl){
					if(c[j].a==c[cc].a) continue;
					if(c[j].a==c[cc].b) continue;
					if(c[j].b==c[cc].a) continue;
					if(c[j].b==c[cc].b) continue;
					//cout<<c[j].a<<" "<<c[j].b<<" "<<c[cc].a<<" "<<c[cc].b<<" * "<<c[j].xl<<" * "<<c[cc].xl<<endl;
					ans++;
				}
				cc++;
			}
		}
		ans>>=1;
        printf("Case %d: %lld\n",cas++,ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/88757155