您的位置:首页 > 其它

fzu 2231 平行四边形数

2016-05-02 22:55 351 查看
题意:给出n个点,问哪四个点可以组成平行四边形

思路;要判别一个四边形是否是平行四边形,一个等价的判断条件是 两条边平行且相等,这样就是平行四边形,并且平行具有传递性,如果a//b,b//c,那么a//c,那么设g[i]为第i条边已经能组成平行四边形的个数,那么如果j//i且d[j]==d[i],g[j]=g[i]+1,可以在o(n)下处理,但要提前排好序,有点像dp的重复子问题,细节看代码

链接:http://acm.fzu.edu.cn/problem.php?pid=2231

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;

const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
int x[505], y[505];

typedef long long ll;

struct node
{
int x, y;
}a[505];//存所有的点

struct edge
{
int x1,y1,x2, y2,k2,k1;
ll d;
double k,b;
} b[300000];//存的是所有的边 ,最多有500*499条边

int g[300000];

ll cal(int x1, int y1, int x2, int y2)//边长
{
return (ll)abs(x1-x2)*abs(x1-x2) + (ll)abs(y1-y2)*abs(y1-y2);
}

int gcd(int a,int b)
{
return b==0?a:gcd(b, a%b);
}

void calk(int x1, int y1, int x2, int y2,int &x, int &y)//计算该边斜率
{
x = x1-x2;
y = y1 - y2;
int d = gcd(x, y);
x/=d, y/=d;
}

bool cmp(const edge &a, const edge &b)//先按距离排序,再按斜率排序
{
if(a.d!=b.d)
return a.d<b.d;
else
{
return a.k<b.k;
}
}

int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i=0; i<n; i++)
{
scanf("%d%d", &a[i].x, &a[i].y);
}
int cnt = 0;
for(int i=0; i<n; i++)
{
for(int j=i+1; j<n; j++)
{
b[cnt].x1 = a[i].x,b[cnt].y1 = a[i].y;
b[cnt].x2 = a[j].x,b[cnt].y2 = a[j].y;
b[cnt].d =cal(a[i].x, a[i].y,a[j].x,a[j].y;
if(b[cnt].x1==b[cnt].x2)
b[cnt].k = inf;
else
{
calk(a[i].x, a[i].y,a[j].x,a[j].y, b[cnt].k2,b[cnt].k1);
b[cnt].k = (double)b[cnt].k1/b[cnt].k2;
b[cnt].b = (double)b[cnt].y1 - b[cnt].k*b[cnt].x1;
}
cnt++;//y = kx+b;
}
}
int ans =0;
memset(g, 0, sizeof(g));
sort(b, b+cnt, cmp);
for(int i= 1; i<cnt; i++)
{
if(b[i].d==b[i-1].d&&(fabs(b[i].k-b[i-1].k)<eps))//两条边边长相等,斜率相等
{
if(b[i].x1==b[i].x2)//平行y轴,则斜率为无限大
{
if(b[i].x1!=b[i-1].x1)
{
g[i]=g[i-1]+1;
ans += g[i];
}
}
else if(fabs(b[i].k-0)<eps) //平行x轴, 则斜率为0
{
if(b[i].y1!=b[i-1].y1)
{
g[i]=g[i-1]+1;
ans += g[i];
}
}
else
{
if(fabs(b[i].b-b[i-1].b)>eps)//两直线必须保证b不相等,
{
g[i]=g[i-1]+1;
ans += g[i];
}
}
}

}
printf("%d\n", ans/2);//因为一个平行四边有两组边平行且相等,所以重复算了两次
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息