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; }