fzu 2231 平行四边形数

来源:互联网 发布:linux设置后不为中文 编辑:程序博客网 时间:2024/05/22 08:13

题意:给出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;}


0 0
原创粉丝点击