这应该算是一道很经典的计算几何题吧。
另外,类似的做法可以拓展到多边形面积并。
首先求出所有的交点,然后用所有顶点的x坐标和交点的x坐标把原来的图形分割出来。显然,每一个分割块中,一定由若干个梯形组成(可能退化)。
那么对于每一个分割块,把梯形简化为其中位线,求中位线的覆盖再呈上分割块的宽度,累加入答案即可。
采用O(NlogN)的线段覆盖,加上分割线有O(N^2)条,总时间O(N^3logN)。
AC代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define inf 1e100 #define ld long double #define N 355 using namespace std; int n,cnt,tot; struct point{ ld x,y; }a[N][3],c[N],p[N*N]; struct line{ point p,v; }l[N][3]; point operator -(point u,point v){ u.x-=v.x; u.y-=v.y; return u; } point operator +(point u,point v){ u.x+=v.x; u.y+=v.y; return u; } ld crs(point u,point v){ return u.x*v.y-u.y*v.x; } bool havitr(line x,line y){ return crs(y.p-x.p,x.v)*crs(y.p+y.v-x.p,x.v)<0 && crs(x.p-y.p,y.v)*crs(x.p+x.v-y.p,y.v)<0; } point itr(line x,line y){ ld t=crs(y.v,x.p-y.p)/crs(x.v,y.v); x.p.x+=t*x.v.x; x.p.y+=t*x.v.y; return x.p; } bool cmp(point u,point v){ return u.x<v.x || u.x==v.x && u.y<v.y; } void add(int i,int k,int u,int v){ l[i][k].p=a[i][u]; l[i][k].v=a[i][v]-a[i][u]; } int main(){ scanf("%d",&n); int i,j,x,y; for (i=1; i<=n; i++){ for (j=0; j<3; j++){ double u,v; scanf("%lf%lf",&u,&v); a[i][j].x=u; a[i][j].y=v; p[++cnt]=a[i][j]; } sort(a[i],a[i]+3,cmp); if (crs(a[i][2]-a[i][0],a[i][1]-a[i][0])>0){ add(i,0,0,2); add(i,1,2,1); add(i,2,1,0); } else{ add(i,0,2,0); add(i,1,0,1); add(i,2,1,2); } } for (i=2; i<=n; i++) for (j=1; j<i; j++) for (x=0; x<3; x++) for (y=0; y<3; y++) if (havitr(l[i][x],l[j][y])) p[++cnt]=itr(l[i][x],l[j][y]); sort(p+1,p+cnt+1,cmp); ld ans=0; int tot; line t; t.v.x=0; t.v.y=2*inf; t.p.y=-inf; for (i=2; i<=cnt; i++) if (p[i].x!=p[i-1].x){ t.p.x=(p[i-1].x+p[i].x)/2; tot=0; for (j=1; j<=n; j++) if (havitr(l[j][0],t)){ ld u=itr(l[j][0],t).y,v=(havitr(l[j][1],t))?itr(l[j][1],t).y:itr(l[j][2],t).y; if (u>v) swap(u,v); c[++tot].x=u; c[tot].y=v; } sort(c+1,c+tot+1,cmp); ld u=-inf,v=-inf,tmp=0; for (j=1; j<=tot; j++) if (c[j].x>v){ tmp+=v-u; u=c[j].x; v=c[j].y; } else if (c[j].y>v) v=c[j].y; tmp+=v-u; ans+=tmp*(p[i].x-p[i-1].x); } printf("%.2f\n",(double)ans); return 0; }
by lych
2016.3.5