题目
https://www.luogu.com.cn/problem/P4196
思路
求半平面交:
- 先极角排序,如果极角相同,保留最左边那一个
- 维护一个双端队列,考虑加入一个半平面:
-
while deque顶端的两个半平面的交点在当前半平面外:删除deque顶端的半平面。
-
while deque底部的两个半平面的交点在当前半平面外:删除deque底部的半平面。
-
将新半平面加入deque顶端。
-
- 去除多余的半平面:
-
while deque顶端的两个半平面的交点在底部半平面外:删除deque顶端的半平面。
-
while deque底部的两个半平面的交点在顶端半平面外:删除deque底部的半平面。
-
重复上述两条直到不能删除为止。
-
后面根据交点求面积就行
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1077;
const double eps=1e-10;
struct node
{
double x,y;
node(double _x=0,double _y=0):x(_x),y(_y){}
node operator + (const node &a) const {return node(x+a.x,y+a.y);}
node operator - (const node &a) const {return node(x-a.x,y-a.y);}
void operator += (const node &a) {this->x+=a.x,this->y+=a.y;}
void operator -= (const node &a) {this->x-=a.x,this->y-=a.y;}
node operator * (const double &a) const {return node(x*a,y*a);}
node operator / (const double &a) const {return node(x/a,y/a);}
void operator *= (const double &a) {this->x*=a,this->y*=a;}
void operator /= (const double &a) {this->x/=a,this->y/=a;}
}Q[N],P[N];
double cp(node A,node B){return A.x*B.y-A.y*B.x;}
double pp(node A,node B){return A.x*B.x+A.y*B.y;}
struct line
{
node a,b; double k;
line(node _a,node _b):a(_a),b(_b){k=atan2(b.y,b.x);};
line(){};
bool operator < (const line &t)const {return k<t.k;}
}yjy[N],aii[N];
node get(line A,line B)
{
node C=A.a-B.a;
double t=cp(B.b,C)/cp(A.b,B.b);
return A.a+A.b*t;
}
int L=1,R=1,n,tot;
void work()
{
aii[L]=yjy[1];
for(int i=2; i<=tot; i++)
{
while(L<R&&cp(yjy[i].b,P[R-1]-yjy[i].a)<=eps) --R;
while(L<R&&cp(yjy[i].b,P[L]-yjy[i].a)<=eps) ++L;
aii[++R]=yjy[i];
if(fabs(cp(aii[R].b,aii[R-1].b))<=eps)
{
R--;
if(cp(aii[R].b,yjy[i].a-aii[R].a)>eps) aii[R]=yjy[i];
}
if(L<R) P[R-1]=get(aii[R-1],aii[R]);
}
while(L<R&&cp(aii[L].b,P[R-1]-aii[L].a)<=eps) R--;
if(R-L<=1) return;
P[R]=get(aii[L],aii[R]);
}
void solve()
{
double ans=0;
for(int i=L; i<=R; i++) if(i==R) ans+=cp(P[i],P[L]);else ans+=cp(P[i],P[i+1]);
printf("%.3lf",ans/2);
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
int m; scanf("%d",&m);
for(int j=1; j<=m; j++) scanf("%lf%lf",&Q[j].x,&Q[j].y);
for(int j=1; j<=m; j++)
{
tot++;
if(j==m) yjy[tot]=line(Q[j],Q[1]-Q[j]);
else yjy[tot]=line(Q[j],Q[j+1]-Q[j]);
}
}
sort(yjy+1,yjy+tot+1);
work(); solve();
}