bzoj1845【CQOI2005】三角形面积并

来源:互联网 发布:dubstep软件怎么用 编辑:程序博客网 时间:2024/05/22 19:17

1845: [Cqoi2005] 三角形面积并

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 1066  Solved: 282
[Submit][Status][Discuss]

Description

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

Input

第一行为n(N < = 100), 即三角形的个数 以下n行,每行6个整数x1, y1, x2, y2, x3, y3,代表三角形的顶点坐标。坐标均为不超过10 ^ 6的实数,输入数据保留1位小数

Output

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

Sample Input

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

Sample Output

1.75



经典的扫描线问题。

先求出所有线段交点的横坐标,然后排序去重。

考虑每两个相邻的横坐标,中间夹得部分一定是若干个不相交的梯形(三角形)。

根据梯形面积公式,可以想到以下方法:对于每一个区间,我们取中点,求出这条直线被所有三角形覆盖的长度,然后乘以区间宽度,就是这个区间内的面积。

于是问题最终转化为求线段长度并,方法同bzoj2178。

这道题我调了一下午+一晚上,后来发现第二个数据有精度误差,ans-eps才能过。




#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#define F(i,j,n) for(int i=j;i<=n;i++)#define D(i,j,n) for(int i=j;i>=n;i--)#define ll long long#define maxn 100005#define eps 1e-8using namespace std;int n,tot,cnt;double last,ans,pos[maxn];struct P{double x,y;}p[105][3];struct L{P a,b;}l[105][3];struct seg{double l,r;}f[105];inline P operator -(P a,P b){return (P){a.x-b.x,a.y-b.y};}inline double operator *(P a,P b){return a.x*b.y-a.y*b.x;}//叉积 inline double operator /(P a,P b){return a.x*b.x+a.y*b.y;}//点积 inline P inter(L l1,L l2){double k1=(l2.b-l1.a)*(l1.b-l1.a),k2=(l1.b-l1.a)*(l2.a-l1.a),t=k1/(k1+k2);return (P){l2.b.x+(l2.a.x-l2.b.x)*t,l2.b.y+(l2.a.y-l2.b.y)*t};}inline bool judge(L l1,L l2){return fabs((l1.b.y-l1.a.y)*(l2.b.x-l2.a.x)-(l1.b.x-l1.a.x)*(l2.b.y-l2.a.y))>eps;}inline bool cmp(seg a,seg b){return fabs(a.l-b.l)<=eps?a.r<b.r:a.l<b.l;}inline double dcmp(double x){if (fabs(x)<=eps) return 0;else return x<0?-1:1;}inline bool cross(P a1,P a2,P b1,P b2){double c1=(a2-a1)*(b1-a1),c2=(a2-a1)*(b2-a1),c3=(b2-b1)*(a1-b1),c4=(b2-b1)*(a2-b1);return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;}inline double calc(double x){L ln=(L){(P){x,0},(P){x,1}};int num;double y[4],h,ret=0;cnt=0;F(i,1,n){double mn=min(p[i][0].x,min(p[i][1].x,p[i][2].x)),mx=max(p[i][0].x,max(p[i][1].x,p[i][2].x));if (x<mn+eps||x>mx-eps) continue;num=0;F(j,0,2) if (judge(l[i][j],ln)){P tmp=inter(l[i][j],ln);if ((l[i][j].a-tmp)/(l[i][j].b-tmp)>-eps) continue;y[++num]=tmp.y;}if (num>1) f[++cnt]=(seg){y[1],y[2]};}F(i,1,cnt) if (f[i].l>f[i].r) swap(f[i].l,f[i].r);sort(f+1,f+cnt+1,cmp);F(i,1,cnt){if (i==1||f[i].l>h+eps) ret+=f[i].r-f[i].l,h=f[i].r;else if (f[i].r>h+eps) ret+=f[i].r-h,h=f[i].r;}return ret;}int main(){scanf("%d",&n);F(i,1,n) F(j,0,2) scanf("%lf%lf",&p[i][j].x,&p[i][j].y),pos[++tot]=p[i][j].x;F(i,1,n) l[i][0]=(L){p[i][1],p[i][2]},l[i][1]=(L){p[i][0],p[i][2]},l[i][2]=(L){p[i][0],p[i][1]};F(i,1,n-1) F(j,i+1,n) F(k1,0,2) F(k2,0,2)if (cross(l[i][k1].a,l[i][k1].b,l[j][k2].a,l[j][k2].b)) pos[++tot]=inter(l[i][k1],l[j][k2]).x;sort(pos+1,pos+tot+1);last=pos[1];F(i,2,tot)if (fabs(pos[i]-last)>eps){ans+=calc((pos[i]+last)/2)*(pos[i]-last);last=pos[i];}printf("%.2lf\n",ans-eps);return 0;}


0 0
原创粉丝点击