【BZOJ 4445】[Scoi2015]小凸想跑步 半平面交

236 篇文章 0 订阅
8 篇文章 0 订阅
半平面交解不等式方程组
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define eps 1e-10
#define maxn 500021
using namespace std;
int n,cnt,tot;
double all;
struct P{
	double x,y;
	void init(){scanf("%lf%lf",&x,&y);}
	P(double a=0,double b=0):x(a),y(b){}
}p[maxn];
typedef P vec;
double operator*(P a,P b){return a.x*b.y-a.y*b.x;}
vec operator-(P a,P b){return vec(a.x-b.x,a.y-b.y);}
P operator+(P a,vec b){return P(a.x+b.x,a.y+b.y);}
vec operator/(vec a,double t){return vec(a.x/t,a.y/t);}
vec operator*(vec a,double t){return vec(a.x*t,a.y*t);}
bool dcmp(double a,double b){return fabs(a-b)<=eps;}
struct Line{
	P a;vec b;
	double slop;
	bool operator<(const Line& y)const{
		if(fabs(slop-y.slop)>eps)return slop<y.slop;
		return b*(y.a-a)<0;
	}
}l[maxn],q[maxn];

void build(){
	scanf("%d",&n);
	p[1].init(),p[2].init();
	double a,b,c,x,y;p[n+1]=p[1];
	for(int j,i=3;i<=n+1;i++){
		if(i<=n)p[i].init();
		j=i-1;
		a=p[1].y-p[2].y-p[j].y+p[i].y;
		b=p[2].x-p[1].x-p[i].x+p[j].x;
 		c=(p[2].x*p[1].y-p[1].x*p[2].y+p[j].x*p[i].y-p[i].x*p[j].y)*-1;
		l[++cnt].a= fabs(a)>eps ? P(-c/a,0) : P(0,-c/b);
		l[cnt].b=vec(-b,a);
	}
	for(int i=1;i<=n;i++)all+=p[i]*p[i+1];
	
	for(int i=1;i<=n;i++){
		l[++cnt].a=p[i];
		l[cnt].b=p[i+1]-p[i];
	}
	for(int i=1;i<=cnt;i++)l[i].slop=atan2(l[i].b.y,l[i].b.x);
	sort(l+1,l+1+cnt);
	for(int i=1;i<=cnt;i++){
		if(!dcmp(l[i].slop,l[i-1].slop)||i==1)l[++tot]=l[i];
	}cnt=tot;
}

P Q(Line aa,Line bb){
	P A=aa.a,B=bb.a;
	vec a=aa.b,b=bb.b,c=A-B;
	double k=(b*c)/(a*b);
	return A+a*k;
}
bool judge(Line a,Line b,Line c){
	P x=Q(a,b);
	return (x-c.a)*c.b>0;
}
void solve(){
	q[1]=l[1];
	int L=1,R=1;
	for(int i=2;i<=cnt;i++){
		while(L<R&&judge(q[R-1],q[R],l[i]))R--;
		while(L<R&&judge(q[L],q[L+1],l[i]))L++;
		q[++R]=l[i];
	}
	while(L<R&&judge(q[R-1],q[R],q[L]))R--;
	q[R+1]=q[L];tot=0;
	for(int i=L;i<=R;i++){
		p[++tot]=Q(q[i],q[i+1]);
	}p[tot+1]=p[1];
}
int main(){
	build();
	solve();
	double ans=0;
	for(int i=1;i<=tot;i++)
		ans+=p[i]*p[i+1];
	if(tot<3){puts("0.0000");return 0;}
	all=fabs(all),ans=fabs(ans);
	ans=ans/all;
	printf("%.4lf",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值