半平面交。
抄一份代码de一下午bug。
抄板选手的日常。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 typedef long long LL;
11 typedef double db;
12 const db eps=1e-10;
13 const int N=50007;
14 using namespace std;
15 int n,cnt,tot;
16
17 template<typename T>void read(T &x) {
18 char ch=getchar(); x=0; T f=1;
19 while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
20 if(ch==‘-‘) f=-1,ch=getchar();
21 for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f;
22 }
23
24 struct pt {
25 db x,y;
26 pt(db x=0,db y=0):x(x),y(y){}
27 }p[N];
28 typedef pt vc;
29
30 vc operator + (vc A,vc B) { return vc(A.x+B.x,A.y+B.y);}
31 vc operator - (vc A,vc B) { return vc(A.x-B.x,A.y-B.y);}
32 vc operator * (vc A,db p) { return vc(A.x*p,A.y*p);}
33 vc operator / (vc A,db p) { return vc(A.x/p,A.y/p);}
34 bool operator <(const vc&A,const vc&B) { return A.x<B.x||(A.x==B.x&&A.y<B.y);}
35 int dcmp(double x) { if(fabs(x)<eps) return 0; else return x<0?-1:1;}
36 bool operator == (const vc&A,const vc&B) { return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0; }
37
38 db dot(vc A,vc B) { return A.x*B.x+A.y*B.y; }
39 db length(vc A) { return dot(A,A); }
40 db cross(vc A,vc B) { return A.x*B.y-A.y*B.x; }
41
42 struct ln {
43 pt a,b; db slop;
44 friend bool operator <(const ln&A,const ln&B) {
45 return A.slop==B.slop?cross(A.b-A.a,B.b-A.a)>0:A.slop<B.slop;
46 }
47 }L[N],a[N],que[N];
48
49 db polygonArea(int n) {
50 if(n<3) return 0;
51 db res=0;
52 for(int i=1;i<n-1;i++)
53 res+=cross(p[i]-p[0],p[i+1]-p[0]);
54 return fabs(res)/2;
55 }
56
57 pt inter(ln A,ln B) {
58 pt res;
59 db s1=cross(B.b-A.a,A.b-A.a);
60 db s2=cross(A.b-A.a,B.a-A.a);
61 db k=s1/(s1+s2);
62 res.x=B.b.x+(B.a.x-B.b.x)*k;
63 res.y=B.b.y+(B.a.y-B.b.y)*k;
64 return res;
65 }
66
67 bool ck(ln A,ln B,ln P) {
68 pt pp=inter(A,B);
69 return cross(P.b-P.a,pp-P.a)<0;
70 }
71
72 db solve() {
73 sort(L+1,L+cnt+1);
74 for(int i=1;i<=cnt;i++) {
75 if(L[i].slop!=L[i-1].slop) tot++;
76 a[tot]=L[i];
77 }
78 int ql=1,qr=0;
79 L[++qr]=a[1]; L[++qr]=a[2];
80 for(int i=3;i<=tot;i++) {
81 while(qr>ql&&ck(L[qr-1],L[qr],a[i])) qr--;
82 while(qr>ql&&ck(L[ql+1],L[ql],a[i])) ql++;
83 L[++qr]=a[i];
84 }
85 while(qr>ql&&ck(L[qr-1],L[qr],L[ql])) qr--;
86 while(qr>ql&&ck(L[ql+1],L[ql],L[qr])) ql++;
87 L[qr+1]=L[ql];
88 cnt=0;
89 for(int i=ql;i<=qr;i++)
90 p[cnt++]=inter(L[i],L[i+1]);
91 return polygonArea(cnt);
92 }
93
94 int main() {
95 read(n);
96 for(int i=1;i<=n;i++) {
97 int k;
98 read(k);
99 for(int j=1;j<=k;j++) { read(p[j].x);read(p[j].y); }
100 for(int j=1;j<k;j++) {
101 L[++cnt].a=p[j]; L[cnt].b=p[j+1];
102 }
103 L[++cnt].a=p[k]; L[cnt].b=p[1];
104 }
105 for(int i=1;i<=cnt;i++)
106 L[i].slop=atan2(L[i].b.y-L[i].a.y,L[i].b.x-L[i].a.x);
107 printf("%.3lf\n",solve());
108 return 0;
109 }
110 /*
111 2
112 6
113 -2 0
114 -1 -2
115 1 -2
116 2 0
117 1 2
118 -1 2
119 4
120 0 -3
121 1 -1
122 2 2
123 -1 0
124 */