【BZOJ4445】【SCOI2015】—小凸想跑步(半平面交)

传送门

发现满足面积为最小也就是一号边和其他所有边的夹角的角平分线一侧
裸地半平面交

Debug2h后发现一个x,yx,y写反了。。。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
	return res*f;
}
const int N=200005;
const double eps=1e-8;
struct point{
	double x,y;
	point(double _x=0,double _y=0):x(_x),y(_y){}
	inline void in(){
		x=read(),y=read();
	}
	inline double ang(){
		return atan2(y,x);
	}
	friend inline point operator +(const point &a,const point &b){
		return point(a.x+b.x,a.y+b.y);
	}
	friend inline point operator -(const point &a,const point &b){
		return point(a.x-b.x,a.y-b.y);
	}
	friend inline point operator *(const point &a,const double &b){
		return point(a.x*b,a.y*b);
	}
	friend inline point operator /(const point &a,const double &b){
		return point(a.x/b,a.y/b);
	}
	friend inline double operator *(const point &a,const point &b){
		return a.x*b.y-a.y*b.x;
	}
}a[N],b[N];
inline int sign(double x){
	return fabs(x)<eps?0:(x>0?1:-1);
}
struct line{
	point s,e;
	double rad;
	line(){}
	line(point x,point y){
		s=x,e=y,rad=(y-x).ang();
	}
	friend inline bool operator <(const line &a,const line &b){
		return sign(a.rad-b.rad)==0?sign((a.e-a.s)*(b.e-a.s))>0:sign(a.rad-b.rad)<0;
	}
}p[N],q[N];
inline point insec(const line &a,const line &b){
	double s1=(a.s-a.e)*(b.e-a.e),s2=(b.s-a.e)*(a.s-a.e);
	double k=(sign(s1+s2))?(s2)/(s1+s2):0;
	return b.s+(b.e-b.s)*k;
}
inline bool comp(const line &a,const line &b,const line &c){
	return sign((c.e-c.s)*(insec(a,b)-c.s))<0;
}
int hd,tl,tot,n,m;
double ans,ret;
inline void half(){
	sort(p+1,p+m+1);
	for(int i=1;i<=m;i++){
		if(sign(p[i].rad-p[i-1].rad))tot++;
		p[tot]=p[i];
	}
	q[1]=p[1],q[2]=p[2],hd=1,tl=2;
	for(int i=3;i<=tot;i++){
		while(hd<tl&&comp(q[tl-1],q[tl],p[i]))--tl;
		while(hd<tl&&comp(q[hd],q[hd+1],p[i]))++hd;
		q[++tl]=p[i];
	}
	while(hd<tl&&comp(q[tl-1],q[tl],q[hd]))--tl;
	while(hd<tl&&comp(q[hd],q[hd+1],q[tl]))++hd;
	tot=0,q[tl+1]=q[hd];
	for(int i=hd;i<=tl;i++)b[++tot]=insec(q[i],q[i+1]);
}
inline double area(){
	double res=0;
	for(int i=1;i<=tot;i++)
		res+=b[i]*b[i%tot+1];
	return res/2;
} 
int main(){
	n=read();
	for(int i=1;i<=n;i++)a[i].in();
	for(int i=1;i<=n;i++){p[i]=line(a[i-1],a[i]);if(i!=1)ret+=a[i-1]*a[i];}
	p[1]=line(a[n],a[1]),ret+=(a[n]*a[1]);
	m=n;ret=fabs(ret)/2,a[++n]=a[1];
	for(int i=3;i<=n;i++){
		double A=a[1].y-a[2].y-(a[i-1].y-a[i].y);
		double B=a[2].x-a[1].x-(a[i].x-a[i-1].x);
		double C=(a[1]*a[2])-(a[i-1]*a[i]);
		if(fabs(A)<eps) p[++m]=line(point(0,-C/B),point(0,-C/B)+point(-B,A));
		else p[++m]=line(point(-C/A,0),point(-C/A,0)+point(-B,A));
	}
	half();
	ans=area();
	printf("%.4lf",ans/ret);
}
posted @ 2019-03-26 19:21  Stargazer_cykoi  阅读(122)  评论(0编辑  收藏  举报