[LOJ2008][半平面交]SCOI2015:小凸想跑步

LOJ2008

把每個三角形的面積用叉積表示,每個三角形和0,1,p0,1,p組成的三角形組合可以列出n1n-1個不等式,然後把不等式轉成直線做半平面交即可

Code:

#include<bits/stdc++.h>
#define db long double
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=2e5+5;
struct point{
	db x,y;
	point(){}
	point(db _x,db _y):x(_x),y(_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 point &b){return point(a.x-b.x,a.y-b.y);}
	friend inline point operator * (const point &a,const db &b){return point(a.x*b,a.y*b);}
	friend inline db operator * (const point &a,const point &b){return a.x*b.y-a.y*b.x;}
}p[N];
struct line{
	point x,y;
	db ang;
	line(){}
	line(point _x,point _y):x(_x),y(_y),ang(atan2(y.y,y.x)){}
}l[N];
inline bool lft(line a,point b){return a.y*(b-a.x)>=0;}
inline bool cmp(line a,line b){
	if(fabs(a.ang-b.ang)==0) return lft(a,b.x);
	return a.ang<b.ang;
}
inline point itse(line a,line b){
	point bs=a.x-b.x;
	db tmp=(b.y*bs)/(a.y*b.y);
	return a.x+a.y*tmp;
}
int q[N];
int n,tot;
db ans=0,sum=0;
inline void hp(){
	int hd=1,ta=2;
	sort(l+1,l+tot+1,cmp);
	int pos=1;
	for(int i=2;i<=tot;i++) if(fabs(l[i].ang-l[pos].ang)>0) l[++pos]=l[i];
	tot=pos;
	q[1]=1,q[2]=2;
	for(int i=3;i<=tot;i++){
		while(hd<ta && lft(l[i],itse(l[q[ta-1]],l[q[ta]]))) --ta;
		while(hd<ta && lft(l[i],itse(l[q[hd+1]],l[q[hd]]))) ++hd;
		q[++ta]=i;
	}
	while(hd<ta && lft(l[q[hd]],itse(l[q[ta-1]],l[q[ta]]))) --ta;
	for(int i=hd;i<ta;i++) p[i]=itse(l[q[i]],l[q[i+1]]);
	p[ta]=itse(l[q[ta]],l[q[hd]]);
	for(int i=hd;i<ta;i++) ans+=p[i]*(p[i+1]-p[i]);
	ans+=p[ta]*(p[hd]-p[ta]);
}
int main(){
	n=read();
	for(int i=0;i<n;i++) p[i].x=read(),p[i].y=read();
	p[n]=p[0];
	for(int i=0;i<n;i++) l[++tot]=line(p[i+1],p[i]-p[i+1]),sum+=p[i]*(p[i+1]-p[i]);
	for(int i=1;i<n;i++){
		db a=p[i+1].x-p[i].x-p[1].x+p[0].x;
		db b=p[i+1].y-p[i].y-p[1].y+p[0].y;
		db c=-(p[i]*(p[i+1]-p[i]))+p[0]*(p[1]-p[0]);
		if(fabs(a)>0) l[++tot]=line(point(0,c/a),point(-a,-b)); 
		else if(fabs(b)>0) l[++tot]=line(point(-c/b,0),point(0,-b));
	}
	hp();
	printf("%.4lf",(double)fabs(ans/sum));
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章