%%%PoPoQQQ:http://blog.csdn.net/popoqqq/article/details/42581881
经典的扫描线
首先求出所有直线交点的横坐标,排序,去重
然后对于每个横坐标,两段之间夹的部分一定是一个或多个梯形
因此我们取中位线,求出中位线被所有三角形覆盖区间的区间并的长度,即可计算出这部分的面积
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #define eps 1e-7 using namespace std; inline int dcmp(double a,double b){ if (fabs(a-b)<eps) return 0; if (a>b) return 1; return -1; } struct Point{ double x,y; Point(double x=0,double y=0):x(x),y(y) { } void read(){ scanf("%lf%lf",&x,&y); } }; struct Line{ Point A,B; double k,b; Line(Point a,Point b):A(a),B(b) { } Line(double x1=0,double y1=0,double x2=0,double y2=0){ A.x=x1; A.y=y1; B.x=x2; B.y=y2; } bool dir() { return dcmp(A.x,B.x)==0; } bool calc(){ if (dir()) return 0; k=(B.y-A.y)/(B.x-A.x); b=B.y-k*B.x; return 1; } }L[305]; inline double Cross(Point p1,Point p2,Point p0) { return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } inline double Pd(Line L1,Line L2){ return dcmp(Cross(L1.A,L1.B,L2.A)*Cross(L1.A,L1.B,L2.B),0)<0 && dcmp(Cross(L2.A,L2.B,L1.A)*Cross(L2.A,L2.B,L1.B),0)<0; } inline bool Sub(Line L1,Line L2,Point &t){ if (!Pd(L1,L2)) return 0; if (L1.dir() && L2.dir()) return 0; if (L1.dir()) t=Point(L1.A.x,L2.k*L1.A.x+L2.b); else if (L2.dir()) t=Point(L2.A.x,L1.k*L2.A.x+L1.b); else { if (dcmp(L1.k,L2.k)==0) return 0; t.x=(L2.b-L1.b)/(L1.k-L2.k); t.y=t.x*L1.k+L1.b; } return 1; } int n,m; double sx[150005]; int icnt; struct abcd{ double y; int f; abcd(double y=0,int f=0):y(y),f(f) { } bool operator < (const abcd &B) const{ return dcmp(y,B.y)==0?f>B.f:y<B.y; } }data[505]; int cnt; double Ans; int main() { Point a,b,c; freopen("t.in","r",stdin); freopen("t.out","w",stdout); scanf("%d",&n); for (int i=n;i;i--) { a.read(),b.read(),c.read(); if (Cross(a,b,c)==0) { n--; continue; } sx[++icnt]=a.x; sx[++icnt]=b.x; sx[++icnt]=c.x; L[++m]=Line(a,b); if (!L[m].dir()) L[m].calc(); L[++m]=Line(a,c); if (!L[m].dir()) L[m].calc(); L[++m]=Line(b,c); if (!L[m].dir()) L[m].calc(); } for (int i=1;i<=m;i++) for (int j=i+1;j<=m;j++) if (Sub(L[i],L[j],a)) sx[++icnt]=a.x; sort(sx+1,sx+icnt+1); int pos=0; for (int i=1;i<=icnt;i++) if (i==1 || dcmp(sx[i],sx[i-1])) sx[++pos]=sx[i]; icnt=pos; for (int i=2;i<=icnt;i++) { double Lx=sx[i-1],Rx=sx[i],Mx=(Lx+Rx)/2,lasty; int lastf; cnt=0; for (int i=1;i<=n;i++) { double yy[5]={0}; int ic=0; for (int j=3*i-2;j<=3*i;j++) if (dcmp(L[j].A.x,Mx)*dcmp(L[j].B.x,Mx)<=0) yy[++ic]=L[j].k*Mx+L[j].b; if (ic) { if (ic==3 && dcmp(yy[1],yy[2])==0) swap(yy[2],yy[3]); if (dcmp(yy[1],yy[2])>0) swap(yy[1],yy[2]); data[++cnt]=abcd(yy[1],1); data[++cnt]=abcd(yy[2],-1); } } sort(data+1,data+cnt+1); for (int i=1,j,itmp;i<=cnt;i=j+1) { itmp=data[i].f; for (j=i;j+1<=cnt && itmp;) itmp+=data[++j].f; Ans+=(data[j].y-data[i].y)*(Rx-Lx); } } printf("%.2lf\n",Ans-eps); return 0; }