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
- BZOJ 1845 [Cqoi2005] 三角形面积并 计算几何扫描线
- [扫描线 计算几何] BZOJ 1845 [Cqoi2005] 三角形面积并
- bzoj 1845: [Cqoi2005] 三角形面积并 (扫描线+计算几何)
- [BZOJ1845][Cqoi2005] 三角形面积并(计算几何+扫描线)
- bzoj 1845: [Cqoi2005] 三角形面积并(计算几何)
- BZOJ 1845 Cqoi2005 三角形面积并 扫描线
- bzoj1845【CQOI2005】三角形面积并
- bzoj1845: [Cqoi2005] 三角形面积并
- BZOJ 1845 CQOI 2005 三角形面积并 扫描线
- bzoj1845 三角形面积并 计算几何
- BZOJ 1845三角形面积并
- bzoj-1845 三角形面积并
- bzoj 4561: [JLoi2016]圆的异或并 (计算几何+扫描线+splay)
- [BZOJ 2731][HNOI 2012]三角形覆盖问题(计算几何+扫描线暴力)
- 站军姿(计算几何 多三角形覆盖面积)
- hdu4709 herding 计算几何 三角形面积 枚举
- hdu 4709 - Herding【计算几何-三角形面积】
- 计算几何(知三角形三点坐标,求三角形的面积)
- 内部类
- 独立主机(云主机、vps)快速安装SSL证书教程
- 大数据
- android studio 与eclipse创建命名空间时候的区别
- VUE-cli 下使用VUX-UI 最基本配置
- bzoj 1845: [Cqoi2005] 三角形面积并 (扫描线+计算几何)
- c# 线程中如何控制控件焦点
- iOS应用沙盒
- 如何在maven工程中加载oracle驱动
- wkhtmltopdf
- C++ 多线程
- android studio 导入项目,目录中存在,As中不显示
- Ogre 绘制立方体
- filter注入service报空指针