半平面交
就是一堆向量的左侧平面的交集
最简单的是求面积
写下来几个公式:
叉积公式(^):\(x_a*y_b-x_b*y_a\),这个东西可以求面积,注意面积是绝对值
交点公式:用点向法表示直线,o是起点,v是向量
\(b.o+b.v*(((b.o-a.o)\text^a.v)/(a.v\text^b.v))\)
注意这里求出的不只是向量的交点,而是两个向量所在直线的交点
下面就是代码了Luogu P4196
code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=505;
struct VEC{
double x,y;
VEC(){}VEC(double a,double b){x=a;y=b;}
void read(){scanf("%lf%lf",&x,&y);}
VEC operator + (VEC a)const{return VEC(x+a.x,y+a.y);}
VEC operator - (VEC a)const{return VEC(x-a.x,y-a.y);}
VEC operator * (double a)const{return VEC(x*a,y*a);}
VEC operator / (double a)const{return VEC(x/a,y/a);}
double operator * (VEC a)const{return x*a.x+y*a.y;}
double operator ^ (VEC a)const{return x*a.y-y*a.x;}
};
struct LNE{
VEC o,v;double ang;
LNE(){ang=atan2(v.y,v.x);}
LNE(VEC a,VEC b){o=a;v=b;ang=atan2(v.y,v.x);}
}q[N],l[N];
bool left(LNE a,LNE b){return (a.v^(b.o-a.o))<0;}
bool comLNE(LNE a,LNE b){
if(a.ang!=b.ang)return a.ang<b.ang;
return left(a,b);
}
VEC cro(LNE a,LNE b){return b.o+b.v*(((b.o-a.o)^a.v)/(a.v^b.v));}
bool jud(LNE now,LNE ltp,LNE top){
return (now.v^(cro(ltp,top)-now.o))<0;
}
int ql,qr,cnt;
double ans;
signed main(){
int n=read();
while(n--){
int m=read()-1;
VEC fi,lt,nw;fi.read();lt=nw=fi;
while(m--)nw.read(),l[++cnt]=LNE(lt,nw-lt),lt=nw;
l[++cnt]=LNE(lt,fi-lt);
}
sort(l+1,l+cnt+1,comLNE);ql=1;qr=0;
q[++qr]=l[1];
fo(i,2,cnt){
if(l[i].ang==l[i-1].ang)continue;
while(ql<qr&&jud(l[i],q[qr-1],q[qr]))qr--;
while(ql<qr&&jud(l[i],q[ql],q[ql+1]))ql++;
q[++qr]=l[i];
}
while(ql<qr&&jud(q[ql],q[qr-1],q[qr]))qr--;
VEC beg=cro(q[ql],q[ql+1]);
fo(i,ql+1,qr-2)ans+=(cro(q[i],q[i+1])-beg)^(cro(q[i+1],q[i+2])-beg)/2;
ans+=(cro(q[qr-1],q[qr])-beg)^(cro(q[qr],q[ql])-beg)/2;
printf("%.3lf",ans);
}
QQ:2953174821