• 【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);
    }
    
  • 相关阅读:
    开源分布式任务调度工具,和你一起记住生命中每一个重要的时刻
    寒假学习进度
    寒假学习进度
    寒假学习进度
    寒假学习进度
    js第三个阶段的面试题
    vue3保证你看懂watch和watchEffect的详细详细使用
    VMtool 安装与使用
    PHP 远程 debug
    一些有趣的编程名言
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145594.html
Copyright © 2020-2023  润新知