简述
面积的大小关系可以用叉积的形式列出一些不等式,然后为了保证点在多边形内还要把每条边看做半平面加进去。最后做一遍半平面交。
形如
ax+by+c>0
的不等式,可以通过如下方法来构造一个半平面。
vec make(double a, double b, double c)
{
double x, y;
x=fabs(b)>eps?0:-c/a;
y=fabs(b)>eps?-c/b:0;
return vec(point(x,y),b,-a);
}
然后就叉积算算面积,再输出比值就好了。
代码
//半平面交
#include <cstdio>
#include <algorithm>
#include <cmath>
#define maxn 300000
#define eps 1e-8
#define finf 1e60
using namespace std;
struct point
{
double x, y;
point(double x, double y):x(x),y(y){}
point(){}
}pt[maxn], _;
struct vec
{
point pt;
double x, y, th;
vec(point pt, double x, double y):pt(pt),x(x),y(y){}
vec(){}
}seg[maxn], q[maxn];
int N, tot, x[maxn], y[maxn];
double a[maxn], b[maxn], S1, S2;
point operator+(point p, vec v){return point(p.x+v.x,p.y+v.y);}
vec operator-(point p1, point p2){return vec(p2,p1.x-p2.x,p1.y-p2.y);}
double operator*(vec v1, vec v2){return v1.x*v2.y-v1.y*v2.x;}
vec operator+(vec v1, vec v2){return vec(_,v1.x+v2.x,v1.y+v2.y);}
vec operator-(vec v1, vec v2){return vec(_,v1.x-v2.x,v1.y-v2.y);}
vec operator*(vec v1, double t){return vec(v1.pt,v1.x*t,v1.y*t);}
bool in(point p, vec v){return (p-v.pt)*v<eps;}
bool operator<(const vec &v1, const vec &v2)
{return fabs(v1.th-v2.th)<-eps?in(v1.pt,v2):v1.th<v2.th;}
point inter(vec v1, vec v2)
{
vec u=v1.pt-v2.pt; double t=v2*u/(v1*v2);
return v1.pt+v1*t;
}
vec make(double a, double b, double c)
{
double x, y;
x=fabs(b)>eps?0:-c/a;
y=fabs(b)>eps?-c/b:0;
return vec(point(x,y),b,-a);
}
void init()
{
int i;
scanf("%d",&N);
for(i=0;i<N;i++)scanf("%d%d",x+i,y+i);
for(i=0;i<N;i++)a[i]=x[(i+1)%N]-x[i], b[i]=y[(i+1)%N]-y[i];
for(i=1;i<N;i++)
seg[++tot]=make(b[0]-b[i],a[i]-a[0],a[0]*y[0]-a[i]*y[i]+b[i]*x[i]-b[0]*x[0]);
for(i=0;i<N;i++)seg[++tot]=point(x[(i+1)%N],y[(i+1)%N])-point(x[i],y[i]);
}
void hpi()
{
int l, r, i, x;
for(i=1;i<=tot;i++)seg[i].th=atan2(seg[i].y,seg[i].x);
sort(seg+1,seg+tot+1);
for(x=1,i=2;i<=tot;i++)if(fabs(seg[i].th-seg[i-1].th)>eps)seg[++x]=seg[i];tot=x;
q[l=r=1]=seg[1];
for(i=2;i<=tot;i++)
{
while(l<r and !in(inter(q[r],q[r-1]),seg[i]))r--;
while(l<r and !in(inter(q[l],q[l+1]),seg[i]))l++;
q[++r]=seg[i];
}
while(l<r and !in(inter(q[r],q[r-1]),q[l]))r--;
while(l<r and !in(inter(q[l],q[l+1]),q[r]))l++;
tot=0;
for(i=l;i<r;i++)pt[++tot]=inter(q[i],q[i+1]);
pt[++tot]=inter(q[r],q[l]);
}
void calc()
{
int i;
point p0(x[0],y[0]);
for(i=3;i<=tot;i++)S1+=fabs((pt[i]-pt[1])*(pt[i-1]-pt[1]));
for(i=2;i<N;i++)S2+=fabs((point(x[i],y[i])-p0)*(point(x[i-1],y[i-1])-p0));
printf("%.4lf",S1/S2);
}
int main()
{
init();
hpi();
calc();
return 0;
}