半平面交,注意直线方向!!!
对于凸包上任意一条边$LINE(p_i,p_{i+1})$都有$S_{\Delta{p_i} {p_{i + 1}}p} < S_{\Delta{p_0} {p_1}p}$
如果我们用叉积来算面积:
$P=(x,y)$
$A=p_0=(x_1,y_1)$
$B=p_1=(x_2,y_2)$
$C=p_{i+1}=(x_3,y_3)$(至于为什么是C为i+1而不是D为i+1,画画图就知道了)
$D=p_i=(x_4,y_4)$
就有不等式:
$(x-x_2,y-y_2)(x-x_1,y-y_1)\leqslant(x-x_3,y-y_3)(x-x_4,y-y_4)$
$\Rightarrow$
$(x-x_2)(y-y_1)-(y-y_2)(x-x_1) \leqslant (x-x_3)(y-y_4)-(y-y_3)(x-x_4)$
$\Rightarrow$
$(-y_1+y_2-y_3-y_4)x+(x_1-x_2+x_3-x_4)y+$$(x_2\times y_1-y_2\times x_1)+(x_4\times y_3-y_4\times x_3) \leqslant 0$
$\Rightarrow$
$(-y_1+y_2-y_3-y_4)x+(x_1-x_2+x_3-x_4)y+\overrightarrow B\times\overrightarrow A+\overrightarrow D\times \overrightarrow C\leqslant 0$
就得到了一个半平面
交一交即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<set>
#include<queue>
#define op operator
#define re(i,l,r) for(int i=(l);i<=(r);i++)
#define rre(i,r,l) for(int i=(r);i>=(l);i--)
using namespace std;
template <typename Q>
void inin(Q &ret)
{
ret=;int f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=;ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
ret=f?-ret:ret;
}
int shurux,shuruy;
const double eps=1e-;
int dcmp(const double &x){return abs(x)<eps?:x<?-:;}
const double pi=acos(-);
const double f(const double &a){return a*a;}
struct xl
{
double x,y;
xl(double x=,double y=):x(x),y(y){}
void in(){inin(shurux),inin(shuruy);x=shurux,y=shuruy;}
bool op < (const xl &rhs)const {return x==rhs.x?y<rhs.y:x<rhs.x;}
xl op + (const double &rhs)const {return xl(x+rhs,y+rhs);}
xl op - (const double &rhs)const {return xl(x-rhs,y-rhs);}
xl op * (const double &rhs)const {return xl(x*rhs,y*rhs);}
xl op / (const double &rhs)const {return xl(x/rhs,y/rhs);}
xl op + (const xl &rhs)const {return xl(x+rhs.x,y+rhs.y);}
xl op - (const xl &rhs)const {return xl(x-rhs.x,y-rhs.y);}
double angle()const {return atan2(y,x);}
double len()const {return sqrt(f(x)+f(y));}
};
double D_(const xl &a,const xl &b){return a.x*b.x+a.y*b.y;}
double X_(const xl &a,const xl &b){return a.x*b.y-a.y*b.x;}
double dis(const xl &a,const xl &b){return sqrt(f(a.x-b.x)+f(a.y-b.y));}
double dis2(const xl &a,const xl &b){return (a.x-b.x)*(a.x+b.x)+f(a.y-b.y);}
double angle(const xl &a,const xl &b){return acos(D_(a,b)/a.len()/b.len());}
struct LINE
{
xl u,v;double rad;
LINE(xl u=xl(,),xl v=xl(,)):u(u),v(v){}
void js(){rad=(v-u).angle();}
bool op < (const LINE &rhs)const {return rad<rhs.rad;}
};
xl p[],ch[];
LINE a[],b[];
bool onleft(const xl &a,const LINE &l){return dcmp(X_(l.v-l.u,a-l.u))>;}
LINE getline2(xl C,xl D)
{
xl A=p[],B=p[];
// if(D_(B-A,D-C)<0)swap(C,D);
double a=(-A.y+B.y-C.y+D.y),b=(A.x-B.x+C.x-D.x),c=X_(B,A)+X_(D,C);
LINE ret(xl(,-c/b),xl(,(-c-a)/b));
if(!dcmp(b))ret=LINE(xl(-c/a,),xl((-c-b)/a,));
if(!onleft(p[],ret)&&!onleft(p[],ret))swap(ret.u,ret.v);
return ret;
}
LINE getline(xl C,xl D)
{
LINE l=getline2(C,D);
int wocao1=onleft(p[],l)|onleft(p[],l);
int wocao2=onleft(C,l)|onleft(D,l);
if(wocao1^wocao2)return l;
else return getline2(D,C);
}
xl getjd(const LINE &a,const LINE &b)
{
xl u=a.u-b.u,v1=a.v-a.u,v2=b.v-b.u;
double t=X_(v2,u)/X_(v1,v2);
return a.u+v1*t;
}
int n,nn;
bool halfplanej(LINE *l)
{
re(i,,n-)l[i].rad=(l[i].v-l[i].u).angle();
sort(l,l+n);
int ll=,rr=;
xl p[n];LINE b[n];b[]=l[];
re(i,,n-)
{
while(ll<rr&&!onleft(p[rr-],l[i]))rr--;
while(ll<rr&&!onleft(p[ll],l[i]))ll++;
b[++rr]=l[i];
if(!dcmp(X_(b[rr].v-b[rr].u,b[rr-].v-b[rr-].u)))
{
rr--;
if(onleft(l[i].u,b[rr]))b[rr]=l[i];
}
if(ll<rr)p[rr-]=getjd(b[rr-],b[rr]);
}
while(ll<rr&&!onleft(p[rr-],b[ll]))rr--;
if(rr-ll<=)return ;
p[rr]=getjd(b[rr],b[ll]);
re(i,ll,rr)ch[nn++]=p[i];
ch[nn]=ch[];return ;
}
double zongarea,yaoarea;
int main()
{
inin(n);
re(i,,n-)p[i].in();
p[n]=p[];
xl temp=p[]-p[];
re(i,,n-)zongarea+=abs(X_(temp,p[i+]-p[i])),temp=temp+(p[i+]-p[i]);
a[]=LINE(p[],p[]);
re(i,,n-)
a[i]=getline2(p[i+],p[i]);
halfplanej(a);
temp=ch[]-ch[];
re(i,,nn-)
yaoarea+=abs(X_(temp,ch[i+]-ch[i])),temp=temp+(ch[i+]-ch[i]);
printf("%.4f",yaoarea/zongarea);
return ;
}