题意:
给出n个三角形,求这n个三角形的面积并;
n<=100,坐标范围在10^6之内;
题解:
裸的扫描线处理面积并问题;
计算几何的数据范围通常不会出的很大,这种题都只是考虑如何处理数据;
这道题我似乎是被卡了一点精度,double换成long double才过掉;
至于解法第一句不是说完了吗23333
咳。。首先就是为了方便处理,我们求出所有线段的交点;
然后用这些交点的横坐标将坐标系划分成一个个竖条;
这些竖条间隔的块内,一定不会出现顶点,一定都是由梯形(三角形)组成的图形;
这个性质实际上保证了一些东西,我们才可以用一些比较优美的方法解出这道题;
考虑枚举每一个块,如何计算这个块内的面积呢?
用中位线去截这个块,得到的区间并长度就是中位线总长度,而总长度*块的宽度就是面积了;
具体的细节理解还是写代码比较好,代码实现也主要是细节;
时间复杂度O(n^3logn),但是写这种题别太纠结复杂度,100范围而已= =;
实现上还是要随心所欲吧,计算几何中写对比写的快重要得多咯;
代码:
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 333
#define pr pair<ld,ld>
using namespace std;
typedef long double ld;
const ld EPS=1e-8;
const ld INF=1e100;
struct Point
{
ld x,y;
Point(){}
Point(ld _,ld __):x(_),y(__){}
void read()
{
double _,__;
scanf("%lf%lf",&_,&__);
x=_,y=__;
}
friend bool operator <(Point a,Point b)
{
if(fabs(a.x-b.x)<EPS)
return a.y<b.y;
return a.x<b.x;
}
friend Point operator +(Point a,Point b)
{
return Point(a.x+b.x,a.y+b.y);
}
friend Point operator -(Point a,Point b)
{
return Point(a.x-b.x,a.y-b.y);
}
friend Point operator *(ld a,Point b)
{
return Point(a*b.x,a*b.y);
}
friend ld operator *(Point a,Point b)
{
return a.x*b.x+a.y*b.y;
}
friend ld operator ^(Point a,Point b)
{
return a.x*b.y-a.y*b.x;
}
}a[N][3],Poi[N*N];
struct Line
{
Point p,v;
Line(){}
Line(Point _,Point __){p=_,v=__-_;}
Point operator [](int k)
{
if(k) return p+v;
else return p;
}
friend bool Cross(Line a,Line b)
{
return (a.v^b[0]-a.p)*(a.v^b[1]-a.p)<-EPS&&(b.v^a[0]-b.p)*(b.v^a[1]-b.p)<-EPS;
}
friend Point getP(Line a,Line b)
{
Point u=a.p-b.p;
ld temp=(b.v^u)/(a.v^b.v);
return a.p+temp*a.v;
}
}l[N][3],T;
pr p[N];
int main()
{
int n,m,i,j,k,x,y,cnt,tot;
ld ans,last,A,B,sum;
scanf("%d",&n);
for(i=1,tot=0;i<=n;i++)
{
a[i][0].read(),a[i][1].read(),a[i][2].read();
Poi[++tot]=a[i][0],Poi[++tot]=a[i][1],Poi[++tot]=a[i][2];
sort(a[i],a[i]+3);
if((a[i][2]-a[i][0]^a[i][1]-a[i][0])>EPS)
l[i][0]=Line(a[i][0],a[i][2]),l[i][1]=Line(a[i][2],a[i][1]),l[i][2]=Line(a[i][1],a[i][0]);
else
l[i][0]=Line(a[i][2],a[i][0]),l[i][1]=Line(a[i][1],a[i][2]),l[i][2]=Line(a[i][0],a[i][1]);
}
for(i=1;i<=n;i++)
{
for(j=1;j<i;j++)
{
for(x=0;x<3;x++)
for(y=0;y<3;y++)
{
if(Cross(l[i][x],l[j][y]))
Poi[++tot]=getP(l[i][x],l[j][y]);
}
}
}
sort(Poi+1,Poi+tot+1);
ans=0,last=Poi[1].x;
T=Line(Point(0,-INF),Point(0,INF));
for(i=2;i<=tot;i++)
{
T.p.x=(last+Poi[i].x)/2;
for(j=1,cnt=0;j<=n;j++)
{
if(Cross(l[j][0],T))
{
A=getP(l[j][0],T).y;
if(Cross(l[j][1],T))
B=getP(l[j][1],T).y;
else
B=getP(l[j][2],T).y;
if(A>B) swap(A,B);
p[++cnt]=pr(A,B);
}
}
sort(p+1,p+cnt+1);
for(j=1,sum=0,A=-INF;j<=cnt;j++)
{
if(p[j].first>A)
{
sum+=p[j].second-p[j].first;
A=p[j].second;
}
else
{
if(p[j].second>A)
sum+=p[j].second-A,A=p[j].second;
}
}
ans+=(Poi[i].x-last)*sum;
last=Poi[i].x;
}
printf("%.2lf\n",(double)ans);
return 0;
}