第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。
输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数
半平面交的面积
judge函数里写成>-eps就WA一个点,玄学问题。。。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #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 1000 #define eps 1e-8 using namespace std; int n,m,cnt,tot; double ans; struct P{double x,y;}p[maxn],a[maxn]; struct L{P a,b;double angle;}l[maxn],q[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } 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 bool operator <(L l1,L l2) { if (fabs(l1.angle-l2.angle)<=eps) return (l1.a-l2.a)*(l1.b-l2.a)>0; else return l1.angle<l2.angle; } 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 a,L b,L t) { P p=inter(a,b); return (p-t.a)*(t.b-t.a)>eps; } inline void hpi() { sort(l+1,l+cnt+1); int head=1,tail=0;tot=1; F(i,2,cnt) { if (fabs(l[i].angle-l[i-1].angle)>eps) tot++; l[tot]=l[i]; } cnt=tot; q[++tail]=l[1];q[++tail]=l[2]; F(i,3,cnt) { while (head<tail&&judge(q[tail],q[tail-1],l[i])) tail--; while (head<tail&&judge(q[head],q[head+1],l[i])) head++; q[++tail]=l[i]; } while (head<tail&&judge(q[tail],q[tail-1],q[head])) tail--; tot=0; F(i,head,tail-1) a[++tot]=inter(q[i],q[i+1]); a[++tot]=inter(q[head],q[tail]); } int main() { n=read(); while (n--) { m=read(); F(i,1,m) p[i].x=read(),p[i].y=read(); F(i,1,m-1) l[++cnt]=(L){p[i],p[i+1]}; l[++cnt]=(L){p[m],p[1]}; } F(i,1,cnt) l[i].angle=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x); hpi(); a[tot+1]=a[1]; F(i,1,tot) ans+=a[i]*a[i+1]; printf("%.3lf\n",ans/2); return 0; }