您的位置:首页 > 其它

bzoj1845 三角形面积并 计算几何

2016-03-05 09:57 555 查看
这应该算是一道很经典的计算几何题吧。

另外,类似的做法可以拓展到多边形面积并。

首先求出所有的交点,然后用所有顶点的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
[3],c
,p[N*N];
struct line{ point p,v; }l
[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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: