LOJ #2008. 「SCOI2015」小凸想跑步(半平面交)

题目
考虑第一个三角形和第 i i i个三角形。
由题意我们需要前者面积小于后者。
LOJ #2008. 「SCOI2015」小凸想跑步(半平面交)_第1张图片
然后画一个这样的图,其中 a a a为第一个三角形的底边(多边形上的边)。
所以显然 v p vp vp向量的右侧的所有点就是满足前者面积小于后者的 P P P
所以我们求出所有的这种分割向量然后做半平面交即可。
这个向量可以用叉积相等(面积相等)+求出交点 v v v来解。
但是这个题真正恶心的是 b b b a a a平行的情况。
但是我们写的标准半平面交是会在所有方向相同的直线中只选一条的。
所以 b b b a a a方向不同,所以我们对他们的起点终点求中点连起来即可。
另外判断一个数是否是 i n f , n a n \mathrm {inf,nan} inf,nan以外的数可以使用
c m a t h \mathrm {cmath} cmath中的 i s f i n i t e ( ) \mathrm {isfinite()} isfinite()

A C   C o d e \mathrm {AC \ Code} AC Code

#include
#define Ct const
#define db double
#define Pt Point
#define eps 1e-10
#define maxn 100005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;

int n,N;
int dcmp(db x){ return x<-eps?-1:x>eps?1:0; }
struct Pt{
	db x,y;Pt(db x=0,db y=0):x(x),y(y){}
	Pt operator +(Ct Pt &B)Ct{ return Pt(x+B.x,y+B.y); }
	Pt operator -(Ct Pt &B)Ct{ return Pt(x-B.x,y-B.y); }
	Pt operator /(Ct db &B)Ct{ return Pt(x/B,y/B); }
	Pt operator *(Ct db &B)Ct{ return Pt(x*B,y*B); }
	db operator *(Ct Pt &B)Ct{ return x*B.y-y*B.x; }
	db operator ^(Ct Pt &B)Ct{ return x*B.x+y*B.y; }
	db Len()Ct{ return sqrt(x*x+y*y); }
	Pt nor()Ct{ return Pt(-y,x); }
}P[maxn],A[maxn],qp[maxn];
int qL,qR;
struct Ln{ Pt s,t;db ang;Ln(Pt a=0,Pt b=0):s(a),t(b){ if(dcmp(b.y-a.y) || dcmp(b.x-a.x)) ang=atan2(b.y-a.y,b.x-a.x);} 
	bool operator <(Ct Ln &B)Ct{ return dcmp(ang-B.ang)?ang<B.ang:(B.t-s)*(t-s)>0; }}L[maxn],q[maxn],Q[maxn];
#define PtLn(a) a.s,a.t-a.s
Pt ITP(Ct Pt &p1,Ct Pt &v1,Ct Pt &p2,Ct Pt &v2){ return p1+(v1*(((p2-p1)*v2)/(v1*v2))); }

int main(){
	scanf("%d",&n);
	rep(i,1,n) scanf("%lf%lf",&P[i].x,&P[i].y);
	db sum = 0;
	rep(i,1,n) Q[i]=Ln(P[i],P[i%n+1]) , sum += (P[i] - P[1]) * (P[i%n+1] - P[1]);
	L[1] = Q[1];
	rep(i,2,n){ L[i].s=ITP(PtLn(Q[1]),PtLn(Q[i]));
		if(isfinite(L[i].s.x) && isfinite(L[i].s.y)){
			L[i].t=L[i].s+Pt(Q[1].t.x-Q[1].s.x-Q[i].t.x+Q[i].s.x,Q[1].t.y-Q[1].s.y-Q[i].t.y+Q[i].s.y);
			L[i]=Ln(L[i].t,L[i].s);
		}
		else L[i]=Ln((Q[1].t+Q[i].s)/2,(Q[1].s+Q[i].t)/2);
	}N=n;
	sort(L+1,L+1+N);
	qL=0,qR=-1;
	rep(i,1,N) if(i==1 || dcmp(L[i].ang-L[i-1].ang)){
		for(;qR-qL+1>=2 && (qp[qR-1]-L[i].s)*(L[i].t-L[i].s)>=0;qR--);
		for(;qR-qL+1>=2 && (qp[qL]-L[i].s)*(L[i].t-L[i].s)>=0;qL++);
		q[++qR]=L[i];if(qR-qL+1>=2) qp[qR-1]=ITP(PtLn(q[qR-1]),PtLn(q[qR]));
	}
	for(;qR-qL+1>=2 && (qp[qR-1]-q[qL].s)*(q[qL].t-q[qL].s)>=0;qR--);
	qp[qR] = ITP(PtLn(q[qL]),PtLn(q[qR]));
	db ans = 0;
	rep(i,qL,qR) ans += (qp[i]-qp[qL])*(qp[i==qR?qL:i+1]-qp[qL]);
	printf("%.4lf\n",ans/sum); 
}

你可能感兴趣的:(计算几何)