题目
类似矩形面积并。把交点拿出来排序扫描线即可。
AC Code:
#include<bits/stdc++.h>
#define maxn 105
#define maxm 50005
#define inf 2e9
#define eps 1e-8
using namespace std;
int n;
struct Point{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
Point operator +(const Point &B)const{ return Point(x+B.x,y+B.y); }
double operator *(const Point &B)const{return x*B.y-y*B.x;}
Point operator *(const double &B)const{return Point(x*B,y*B); }
bool operator <(const Point &B)const{ return x<B.x; }
}P[maxm],Q[maxm];
int tot;
int sgn(double a){ return a<-eps?-1:a>eps?1:0; }
Point Ipt(Point a,Point b,Point c,Point d){
Point u = b - a , v = d - c , w = b - d;
return b + (a-b) * ((w * v) / (u * v));
}
double solve(double mid){
double ret = 0;
int cnt = 0;
static pair<double,double>p[maxm];
for(int i=0;i<n;i++){
double Min = inf , Max = -inf;
for(int k=1;k<=3;k++)
{
Point a = P[3*i+k] , b = P[3*i+k%3+1];
if((a.x <= mid && b.x>=mid) || (a.x>=mid && b.x<=mid))
{
double tmp = Ipt(a,b,Point(mid,0),Point(mid,1)).y;
Min = min(Min , tmp);
Max = max(Max , tmp);
}
}
if(Min<Max)
p[cnt++] = make_pair(Min,Max);
}
sort(p,p+cnt);
double mx=-inf;
for(int i=0;i<cnt;i++){
if(p[i].first > mx)
{
mx = p[i].second;
ret += mx - p[i].first;
}
else{
if(p[i].second > mx){
ret += p[i].second - mx;
mx = p[i].second;
}
}
}
return ret;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lf%lf%lf%lf%lf%lf",&P[i*3+1].x,&P[i*3+1].y,&P[i*3+2].x,&P[i*3+2].y,&P[i*3+3].x,&P[i*3+3].y);
Q[++tot] = P[i*3+1];
Q[++tot] = P[i*3+2];
Q[++tot] = P[i*3+3];
}
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
for(int k1=1;k1<=3;k1++)
for(int k2=1;k2<=3;k2++){
Point a=P[3*i+k1],b=P[3*i+k1%3+1],c=P[3*j+k2],d=P[3*j+k2%3+1];
if(((a-c)*(d-c))*((b-c)*(d-c)) < 0 && ((c-a)*(b-a))*((d-a)*(b-a))<0)
Q[++tot] = Ipt(a,b,c,d);
}
sort(Q+1,Q+1+tot);
double ans = 0;
for(int i=2;i<=tot;i++)
if(sgn(Q[i].x-Q[i-1].x)){
ans += solve((Q[i].x+Q[i-1].x)*0.5) * (Q[i].x-Q[i-1].x);
}
printf("%.2lf\n",ans-eps);
}