bzoj 1845: [Cqoi2005] 三角形面积并 (扫描线+计算几何)

来源:互联网 发布:手机mac是什么意思啊 编辑:程序博客网 时间:2024/05/18 16:55

题目描述

传送门

题目大意:给出n个三角形,求它们并的面积。

题解

MD被卡了一下午精度,各种不爽!!!
同样被卡的同学建议使用long double试一试。。。。
我们把三角形的顶点以及所有交点的横坐标离散,那么相邻两列之间的图形要么是梯形要么是三角形,只要统计出两列上的被覆盖区域的长度,就可以用(上底+下底)*高/2来计算。
统计覆盖区域的话,找出所有的区间,左端点排序后扫一遍就可以了。
有一种情况需要注意,就是三角形的一条边平行于y轴,这种情况计算时只能作为上底,或者只能作为下底,特判一下即可。

代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 300003#define eps 1e-12using namespace std;const long double inf=1e9;long double pos[N],ans[N],ans1[N],L[N],R[N];int n,t,cnt,opt[N];struct data{    long double x,y;     data(long double X=0,long double Y=0){        x=X,y=Y;    }    bool operator ==(const data &a) {        return x==a.x&&y==a.y;    }}p[N],q[N],h[100];data operator +(data a,data b){ return data(a.x+b.x,a.y+b.y);}data operator -(data a,data b){ return data(a.x-b.x,a.y-b.y);}data operator *(data a,double t){return data(a.x*t,a.y*t);}data operator /(data a,double t) {return data(a.x/t,a.y/t);}struct line{    data a[5],b[5];    long double mx,mn;}tr[303];int dcmp(long double x){    if (fabs(x)<eps) return 0;    return x>0?1:-1;}long double cross(data a,data b){    return a.x*b.y-a.y*b.x;}bool check(data a,data b,data c,data d){    long double c1=cross(c-a,b-a); long double c2=cross(d-a,b-a);    long double d1=cross(a-c,d-c); long double d2=cross(b-c,d-c);    return dcmp(c1)*dcmp(c2)<0&&dcmp(d1)*dcmp(d2)<0;}data glt(data a,data a1,data b,data b1)    {        data v=a1-a; data w=b1-b;        data u=a-b;        long double t=cross(w,u)/cross(v,w);        return a+v*t;    }    int cmp(data a,data b){    return a.x<b.x||a.x==b.x&&a.y<b.y;}long double solve(){    sort(q+1,q+t+1,cmp); long double len=0;    long double l=q[1].x; long double r=q[1].y;    for (int i=2;i<=t+1;i++){        if (q[i].x>r||i==t+1) {            len+=r-l;            l=q[i].x; r=q[i].y;        }        else r=max(r,q[i].y);    }    return len;}int check(int i,data a,data b,data c,long double mx,long double mn){    int t=0;     if (a.x==mx) t++,L[i]=min(L[i],a.y),R[i]=max(R[i],a.y);    if (b.x==mx) t++,L[i]=min(L[i],b.y),R[i]=max(R[i],b.y);    if (c.x==mx) t++,L[i]=min(L[i],c.y),R[i]=max(R[i],c.y);    if (t>=2) return 1;    t=0; L[i]=inf; R[i]=-inf;    if (a.x==mn) t++,L[i]=min(L[i],a.y),R[i]=max(R[i],a.y);    if (b.x==mn) t++,L[i]=min(L[i],b.y),R[i]=max(R[i],b.y);    if (c.x==mn) t++,L[i]=min(L[i],c.y),R[i]=max(R[i],c.y);    if (t>=2) return 2;}int main(){    freopen("a.in","r",stdin);//  freopen("my.out","w",stdout);    cnt=0; scanf("%d",&n);    for (int i=1;i<=n;i++){      data x,y,z; L[i]=inf; R[i]=-inf;      cin>>x.x>>x.y;      cin>>y.x>>y.y;      cin>>z.x>>z.y;      tr[i].mx=tr[i].mn=x.x; tr[i].mx=max(y.x,tr[i].mx); tr[i].mx=max(z.x,tr[i].mx);      tr[i].mn=min(y.x,tr[i].mn); tr[i].mn=min(z.x,tr[i].mn);      tr[i].a[1]=x; tr[i].b[1]=y;      tr[i].a[2]=y; tr[i].b[2]=z;      tr[i].a[3]=z; tr[i].b[3]=x;      p[++cnt]=x; p[++cnt]=y; p[++cnt]=z;      opt[i]=check(i,x,y,z,tr[i].mx,tr[i].mn);    }    for (int i=1;i<=n;i++)     for (int k=1;k<=3;k++)      for (int j=i+1;j<=n;j++)       for (int l=1;l<=3;l++)         if (check(tr[i].a[k],tr[i].b[k],tr[j].a[l],tr[j].b[l]))         p[++cnt]=glt(tr[i].a[k],tr[i].b[k],tr[j].a[l],tr[j].b[l]);    for (int i=1;i<=cnt;i++) pos[i]=p[i].x;    sort(pos+1,pos+cnt+1);    cnt=unique(pos+1,pos+cnt+1)-pos-1;    for (int i=1;i<=cnt;i++) {        data a=data(pos[i],-inf); data b=data(pos[i],inf); t=0;        for (int j=1;j<=n;j++){         if (pos[i]<tr[j].mn||pos[i]>tr[j].mx) continue;         if (opt[j]==2&&!dcmp(tr[j].mn-pos[i])) continue;         if (opt[j]==1&&!dcmp(tr[j].mx-pos[i])) {             q[++t].x=L[j]; q[t].y=R[j];             continue;         }         int t1=0;          for (int k=1;k<=3;k++) {            data c=tr[j].a[k]; data d=tr[j].b[k];            if (check(a,b,c,d)) h[++t1]=glt(a,b,c,d);            if (!dcmp(c.x-pos[i])) h[++t1]=c;            if (!dcmp(d.x-pos[i])) h[++t1]=d;         }         t1=unique(h+1,h+t1+1)-h-1;          if (t1<2) continue;         q[++t].x=min(h[1].y,h[2].y); q[t].y=max(h[1].y,h[2].y);        }        ans[i]=solve();        t=0;        for (int j=1;j<=n;j++){         if (pos[i]<tr[j].mn||pos[i]>tr[j].mx) continue;         if (opt[j]==1&&!dcmp(tr[j].mx-pos[i])) continue;         if (opt[j]==2&&!dcmp(tr[j].mn-pos[i])) {             q[++t].x=L[j]; q[t].y=R[j];             continue;         }         int t1=0;          for (int k=1;k<=3;k++) {            data c=tr[j].a[k]; data d=tr[j].b[k];            if (check(a,b,c,d)) h[++t1]=glt(a,b,c,d);            if (!dcmp(c.x-pos[i])) h[++t1]=c;            if (!dcmp(d.x-pos[i])) h[++t1]=d;         }         t1=unique(h+1,h+t1+1)-h-1;         if (t1<2) continue;         q[++t].x=min(h[1].y,h[2].y); q[t].y=max(h[1].y,h[2].y);        }        ans1[i]=solve();    }    long double sum=0;    for (int i=2;i<=cnt;i++) sum+=(ans[i]+ans1[i-1])*(pos[i]-pos[i-1])/2.0;    printf("%.2lf\n",(double)sum);}
0 0
原创粉丝点击