题目主干:
Accept: 225 Submit: 753
Time Limit: 2000 mSec Memory Limit : 32768 KB
Problem Description
在一个平面内给定n个点,任意三个点不在同一条直线上,用这些点可以构成多少个平行四边形?一个点可以同时属于多个平行四边形。
Input
多组数据(<=10),处理到EOF。
每组数据第一行一个整数n(4<=n<=500)。接下来n行每行两个整数xi,yi(0<=xi,yi<=1e9),表示每个点的坐标。
Output
每组数据输出一个整数,表示用这些点能构成多少个平行四边形。
Sample Input
Sample Output
Source
福州大学第十三届程序设计竞赛大体思路:
(1)这里,我们可以把任意两个点看为一组,然后把一组中的两个点用直线连起来,并找到它们的中点。如果有两组直线的中点一样(重合),则这两组中的四个点可以构成一个平行四边形。
(2)如何确定中点是否重合:若有四个点A,B,C,D.坐标分别为(x1,y1),(x2,y2),(x3,y3),(x4,y4)。若直线AC和BD的中点重合。则(x1+x3)/2=(x2+x4)/2,(y1+y3)/2=(y2+y4)/2; 化简得x1+x3=x2+x4,y1+y3=y2+y4。满足此条件时。ABCD四个点能构成一个平行四边形。
主要代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
using namespace std;
struct ssr///使用结构数组,便于查找点的x,y坐标
{
int x;
int y;
} re[501],Map[501*501];///re数组是输入保存点的数据。
///Map数组用来保存两个点组成的组的数据
bool cmp(ssr a,ssr b)///排序规则可更改,排序只是为了方便比较。
{
if(a.x==b.x)
{
return a.y<b.y;
}
else
{
return a.x<b.x;
}
}
int main()
{
int n;
while(cin>>n)
{
for(int i=0; i<n; i++)
{
scanf("%d %d",&re[i].x,&re[i].y);///输入部分,没啥好说的
}
int flag=0;
for(int i=0; i<n-1; i++)
{
for(int j=i+1; j<n; j++)///把每两个点都组和一次
{
Map[flag].x=re[i].x+re[j].x;///计算出所有可能组的x和y的和的大小
Map[flag].y=re[i].y+re[j].y;
flag++;
}
}
sort(Map,Map+flag,cmp);///排序后方便下面的比较
int sum1=0;///sum1是中点相同的组的数量
int sum2=0;///sum2是可组成平行四边形的数量
for(int i=0;i<flag;i++)
{
if(Map[i].x==Map[i-1].x &&Map[i].y==Map[i-1].y)///相当于验证公式x1+x3=x2+x4,y1+y3=y2+y4;若相等,说明这两组的四个点可以组成平行四边形
{
sum1++;
}
else
{
sum2+=((1+sum1)*sum1)/2;///(稍后解释)
sum1=0;
}
}
printf("%d\n",sum2);
}
return 0;
}
其中
sum2+=((1+sum1)*sum1)/2;
可以这样解释。如果有两个组1,2;可以组成的平行四边形有12。一个
如果有三个组1,2,3;可以组成的平行四边形有12,13,23。三个
如果有四个组1,2,3,4;可以组成的平行四边形有12,13,14,23,24,34。六个
满足递增数列1+2+3+4+5........
求和公式((n+1)*n)/2
最后全加到sum2上即可