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;
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12221288.html