2801. 三角形面积并

题目链接

2801. 三角形面积并

给出 n 个三角形,求它们并的面积。

输入格式

第一行为 n,即三角形的个数。

以下 n 行,每行 6 个实数 x1,y1,x2,y2,x3,y3,代表三角形的顶点坐标。

坐标均为不超过 106 的实数,输入数据保留 1 位小数。

输出格式

输出并的面积 u,保留两位小数。

数据范围

1n100

输入样例:

2 0.0 0.0 2.0 0.0 1.0 1.0 1.0 0.0 3.0 0.0 2.0 1.0

输出样例:

1.75

解题思路

扫描线

将所有三角形的端点和交点预处理出来,然后扫描线处理每一小段之间的面积,可以发现每一小段之间是若干个梯形,梯形的高已经确定,需要分别计算上底和下底的总长度,对于左扫描线的上底总长度,对于一个贯穿该扫描线的三角形,需要先特判当前三角形是否存在一条竖直的直线恰好经过该点,其要求该三角形的另外一个端点在右边,否则求出两个点,右扫描线同理,最后区间和并求出各自的贡献即可

n 个三角形最后一个三角形增加的交点个数为 6n6,总的交点个数为 3n(n1),则总点数为 3n2,故:

  • 时间复杂度:O(n3logn)

代码

// Problem: 三角形面积并 // Contest: AcWing // URL: https://www.acwing.com/problem/content/2803/ // Memory Limit: 64 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=105; const double eps=1e-8,inf=1e6; typedef pair<double,double> PDD; int n; PDD tr[N][3],q[N]; PDD operator+(PDD a,PDD b) { return {a.fi+b.fi,a.se+b.se}; } PDD operator-(PDD a,PDD b) { return {a.fi-b.fi,a.se-b.se}; } PDD operator*(PDD a,double t) { return {a.fi*t,a.se*t}; } double operator*(PDD a,PDD b) { return a.fi*b.se-b.fi*a.se; } double operator&(PDD a,PDD b) { return a.fi*b.fi+a.se*b.se; } int sign(double x) { if(fabs(x)<eps)return 0; if(x<0)return -1; return 1; } int dcmp(double x,double y) { if(fabs(x-y)<eps)return 0; if(x<y)return -1; return 1; } bool on_segment(PDD p,PDD a,PDD b) { return sign((p-a)&(p-b))<=0; } PDD get_line_intersection(PDD p,PDD v,PDD q,PDD w) { if(!sign(v*w))return {inf,inf}; PDD u=p-q; double t=w*u/(v*w); PDD o=p+v*t; if(!on_segment(o,p,p+v)||!on_segment(o,q,q+w))return {inf,inf}; return o; } double line_area(double a,int side) { int cnt=0; for(int i=1;i<=n;i++) { if(dcmp(tr[i][2].fi,a)<0||dcmp(a,tr[i][0].fi)<0)continue; if(!dcmp(tr[i][0].fi,a)&&!dcmp(tr[i][1].fi,a)) { if(side)q[++cnt]={tr[i][0].se,tr[i][1].se}; } else if(!dcmp(tr[i][1].fi,a)&&!dcmp(tr[i][2].fi,a)) { if(!side)q[++cnt]={tr[i][1].se,tr[i][2].se}; } else { double d[3]; int t=0; for(int j=0;j<3;j++) { PDD o=get_line_intersection(tr[i][j],tr[i][(j+1)%3]-tr[i][j],{a,-inf},{0,inf*2}); if(dcmp(o.fi,inf))d[t++]=o.se; } if(t) { sort(d,d+t); q[++cnt]={d[0],d[t-1]}; } } } if(!cnt)return 0; for(int i=1;i<=cnt;i++) if(q[i].fi>q[i].se)swap(q[i].fi,q[i].se); sort(q+1,q+1+cnt); double res=0,st=q[1].fi,ed=q[1].se; for(int i=2;i<=cnt;i++) if(q[i].fi<=ed)ed=max(ed,q[i].se); else { res+=ed-st; st=q[i].fi,ed=q[i].se; } res+=ed-st; return res; } double range_area(double l,double r) { return (line_area(l,1)+line_area(r,0))*(r-l)/2; } int main() { scanf("%d",&n); vector<double> xs; for(int i=1;i<=n;i++) { for(int j=0;j<3;j++) { scanf("%lf%lf",&tr[i][j].fi,&tr[i][j].se); xs.pb(tr[i][j].fi); } sort(tr[i],tr[i]+3); } for(int i=1;i<=n;i++) for(int j=1;j<i;j++) for(int p=0;p<3;p++) for(int q=0;q<3;q++) { PDD o=get_line_intersection(tr[i][p],tr[i][(p+1)%3]-tr[i][p],tr[j][q],tr[j][(q+1)%3]-tr[j][q]); if(dcmp(o.fi,inf))xs.pb(o.fi); } sort(xs.begin(),xs.end()); double res=0; for(int i=1;i<xs.size();i++) if(dcmp(xs[i-1],xs[i]))res+=range_area(xs[i-1],xs[i]); printf("%.2lf",res); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16919512.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示

喜欢请打赏

扫描二维码打赏

支付宝打赏