版权声明:转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/82711019
传送门:bzoj4445
题解
,可以枚举除 边之外凸包上的所有边与 边列一个方程,解出式子 中 的值,使得 或 ,这样可以列出 个不等式来限制答案坐标 ,加上之前凸包边的限制。半平面交圈出来的区域就是可行的面积。
详细讲一下如何列方程(??):
设向量之间的叉积运算符号为 ,按逆时针顺序给定凸包上的点 ,图中存在点 ,使得 ,设 。
设 。
考虑 可以用叉积表示:
上面的要求就可以转化为:
展开 得到:
扫描二维码关注公众号,回复:
3359867 查看本文章
最终得到不等式:
记得构造直线时判断方向和特判 为0的情况。要耐心推式子&判断。
代码
#include<bits/stdc++.h>
#define RI register
#define db double
#define eps 1e-10
using namespace std;
const int N=1e5+100;
int n,tot,hd,tl,Q[N<<1];
db pre,nw,whle,area;
struct P{
db x,y;
P(){};
P(db _x_,db _y_){x=_x_;y=_y_;}
}p[N],t[N<<1];
inline db fab(db x){if(x>-eps && x<eps) return 0;return x<eps?(-x):x;}
inline int dcmp(db x){if(x>-eps && x<eps) return 0;return x<eps?(-1):1;}
P operator +(const P&A,const P&B){return P(A.x+B.x,A.y+B.y);}
P operator -(const P&A,const P&B){return P(A.x-B.x,A.y-B.y);}
db operator ^(const P&A,const P&B){return A.x*B.y-A.y*B.x;}
P operator *(const P&A,const db&B){return P(A.x*B,A.y*B);}
P operator /(const P&A,const db&B){return P(A.x/B,A.y/B);}
struct L{
P st,dir;db ang;
L(){};
L(P _st_,P _ed_){st=_st_;dir=_ed_-_st_;ang=atan2(dir.y,dir.x);}
}le[N<<1];
inline bool cmp(const L&A,const L&B){return A.ang<B.ang;}
inline bool onlf(const L&A,const P&B){return dcmp(A.dir^(B-A.st))==1;}
inline P insp(L A,L B)
{
db aa=A.dir^B.dir,bb=B.dir^(A.st-B.st);
return A.st+A.dir*bb/aa;
}
int main(){
RI int i,j,nx,ny;db px,py;P des;
scanf("%d",&n);
scanf("%lf%lf",&p[1].x,&p[1].y);
for(i=2;i<=n;++i){
scanf("%lf%lf",&p[i].x,&p[i].y);
le[++tot]=L(p[i-1],p[i]);
}
le[++tot]=L(p[n],p[1]);p[n+1]=p[1];
for(i=1;i<=n;++i) whle+=p[i]^p[i+1];
pre=p[1]^p[2];
for(i=2;i<=n;++i){
px=p[1].y-p[2].y-p[i].y+p[i+1].y;
py=p[1].x-p[2].x-p[i].x+p[i+1].x;
nx=dcmp(px);ny=dcmp(py);
if(!nx && !ny) continue;
tot++;nw=p[i]^p[i+1];
//一些特判
if(!nx){
if(ny==-1) le[tot]=L(P(1.0,(pre-nw)/py),P(0.0,(pre-nw)/py));
else le[tot]=L(P(0.0,(pre-nw)/py),P(1.0,(pre-nw)/py));
}else if(!ny){
if(nx==-1) le[tot]=L(P((nw-pre)/px,1.0),P((nw-pre)/px,0.0));
else le[tot]=L(P((nw-pre)/px,0.0),P((nw-pre)/px,1.0));
}else{
if(ny==-1) le[tot]=L(P(1.0,(px+pre-nw)/py),P(0.0,(pre-nw)/py));
else le[tot]=L(P(0.0,(pre-nw)/py),P(1.0,(px+pre-nw)/py));
}
}
//半平面交
sort(le+1,le+tot+1,cmp);
hd=tl=1;Q[1]=1;
for(i=2;i<=tot;++i){
for(;hd<tl && (!onlf(le[i],t[tl-1]));--tl);
for(;hd<tl && (!onlf(le[i],t[hd]));++hd);
Q[++tl]=i;
if(dcmp(le[Q[tl]].dir^le[Q[tl-1]].dir)==0){
tl--;
if(onlf(le[Q[tl]],le[i].st)) Q[tl]=i;
}
if(hd<tl) t[tl-1]=insp(le[Q[tl]],le[Q[tl-1]]);
}
for(;hd<tl && (!onlf(le[Q[hd]],t[tl-1]));--tl);
if(hd+1>=tl) {puts("0.0000");return 0;}
t[tl]=insp(le[Q[hd]],le[Q[tl]]);
t[tl+1]=t[hd];
for(i=hd;i<=tl;++i) area+=t[i]^t[i+1];
printf("%.4lf\n",fab(area*0.5)/fab(whle*0.5));
return 0;
}