zoukankan      html  css  js  c++  java
  • bzoj 1845: [Cqoi2005] 三角形面积并

    https://www.lydsy.com/JudgeOnline/problem.php?id=1845

    将所有三角形的端点、交点按x坐标排序,从左往右扫描线

    每相邻两根扫描线a和b之间的形状是若干个不相交的梯形或三角形

    用公式:中位线长度*高 计算面积

    高就是两条扫描线之间的距离

    中位线,计算x=(xa+xb)/2 被覆盖了多长即可

    因为已将三角形端点考虑在内,所以线段相交只需要考虑规范相交即可

    直接套lrj的板子

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    
    const double eps=1e-10;
    const int inf=2e6;
    
    int n;
    struct Point
    {
        double x,y;
        
        Point(double x_=0,double y_=0) : x(x_),y(y_) {}
    }tri[101][4],seg[101];
    
    typedef Point Vector;
    
    double line[100001];
    
    Vector operator - (Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); }
    Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); }
    Vector operator * (Vector A,double p) { return Vector(A.x*p,A.y*p); } 
    
    int dcmp(double x)
    {
        if(fabs(x)<eps) return 0;
        else return x<0 ? -1 : 1;
    }
    
    double Cross(Vector A,Vector B)
    {
        return A.x*B.y-A.y*B.x;
    }
    
    bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
    {
        double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
        return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
    }
    
    Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
    {
        Vector u=P-Q;
        double t=Cross(w,u)/Cross(v,w);
        return P+v*t;
    }
    
    bool cmp(Point a,Point b)
    {
        return a.x<b.x;
    }
    
    double cal(double x)
    {
        Point up(x,-inf),down(x,inf);
        int m=0,k;
        double py[3];
        for(int i=1;i<=n;++i)
        {
             k=0;
             for(int j=0;j<3;++j)
                 if(SegmentProperIntersection(tri[i][j],tri[i][j+1],up,down))
                     py[++k]=GetLineIntersection(tri[i][j],tri[i][j+1]-tri[i][j],up,down-up).y;
             if(k) seg[++m]=Point(min(py[1],py[2]),max(py[1],py[2]));
        }
        if(!m) return 0; 
        sort(seg+1,seg+m+1,cmp);
        double sum=seg[1].y-seg[1].x,r=seg[1].y;
        for(int i=2;i<=m;++i)
            if(dcmp(seg[i].y-r)>0) 
            {
                sum+=seg[i].y-max(r,seg[i].x);
                r=seg[i].y;
            }
        return sum;
    }
    
    int main()
    {
        freopen("data.txt","r",stdin);
        freopen("my.txt","w",stdout); 
        int m=0;
        scanf("%d",&n);
        for(int i=1;i<=n;++i) 
        {
            for(int j=0;j<=2;++j)
            { 
                scanf("%lf%lf",&tri[i][j].x,&tri[i][j].y);
                line[++m]=tri[i][j].x;
            }
            tri[i][3]=tri[i][0];
        }
        for(int i=1;i<n;++i)
            for(int j=i+1;j<=n;++j)
                for(int k=0;k<3;++k)
                    for(int l=0;l<3;++l)
                        if(SegmentProperIntersection(tri[i][k],tri[i][k+1],tri[j][l],tri[j][l+1]))
                            line[++m]=GetLineIntersection(tri[i][k],tri[i][k+1]-tri[i][k],tri[j][l],tri[j][l+1]-tri[j][l]).x;
        double ans=0;
        sort(line+1,line+m+1);
        for(int i=2;i<=m;++i)
            if(dcmp(line[i]-line[i-1])) 
                 ans+=(line[i]-line[i-1])*cal((line[i]+line[i-1])/2);
        printf("%.2lf",ans-eps);
        return 0;
    }
  • 相关阅读:
    ASCII,Unicode,UTF
    C#值类型和引用类型2
    C#中使用Foreach
    CSS基础(2)
    CSS基础
    HTML基础
    MySQL高级
    MySQL和Python交互案例练习(2)
    MySQL和Python交互案例练习(1)
    外键SQL语句的编写
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12221288.html
Copyright © 2011-2022 走看看