scoi2015小凸想跑步

9 篇文章 0 订阅

http://www.lydsy.com/JudgeOnline/problem.php?id=4445

这次是重做,但发现自己被读入优化坑了,不造为什么,反正改了就过了,坑爹~~~double坑爹

scoi2015day1 攻克完成(虽然是看了题解的很水攻克~~)

之前写过思路了,这里不再说了~~~

转成不等关系跑半平面交

(吐槽:还是推不等式ax+by+c<0的时候很坑,手动推起来确实很恶心QAQ)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
#define eps 1e-10
using namespace std;
const int maxn=200000+20;
int dcmp(double x)
{
	if(fabs(x)<eps)return 0;
	return x<0?-1:1;
}
struct point
{
	double x,y;
	point(){}
	point(double _x,double _y)
	{
		x=_x;
		y=_y;
	}
	point operator +(const point &b)
	{
		return point(x+b.x,y+b.y);
	}
	point operator -(const point &b)
	{
		return point(x-b.x,y-b.y);
	}
	point operator *(const double &b)
	{
		return point(x*b,y*b);
	}
};
double cross(point a,point b)
{
	return a.x*b.y-a.y*b.x;
}
double dot(point a,point b)
{
	return a.x*b.x+a.y*b.y;
}
struct line
{
	point p,v;
	double ang;
	line(){}
	line (point _p,point _v)
	{
		p=_p;
		v=_v;
		ang=atan2(v.y,v.x);
	}
	bool operator <(const line&l)const
	{
		return ang<l.ang;
	}
}l[maxn];
bool onleft(point p,line l)
{
	return dcmp(cross(l.v,p-l.p))>0;
}
double x[maxn],y[maxn];
int cnt;
int read()
{
	int res=0;
	char c=getchar();
	for(;c<'0'||c>'9';c=getchar());
	for(;c>='0'&&c<='9';c=getchar())res=res*10+c-'0';
	return res;
}
point getsec(point p1,point v1,point p2,point v2)
{
	double x=cross(p2-p1,v2)/cross(v1,v2);
	return v1*x+p1;
}	
point p[maxn];
line q[maxn];
double hp(line *L,int n)
{
	sort(L+1,L+n+1);

	int first,last;
	q[first=last=0]=L[1];
	for(int i=2;i<=n;i++)
	{
		while(first<last&&!onleft(p[last-1],L[i]))last--;
		while(first<last&&!onleft(p[first],L[i]))first++;
		q[++last]=L[i];
		if(dcmp(cross(q[last].v,q[last-1].v))==0)
		{
			last--;
			if(!onleft(p[last-1],L[i]))q[last]=L[i];
		}
		if(first<last)p[last-1]=getsec(q[last].p,q[last].v,q[last-1].p,q[last-1].v);
	}
	while(first<last&&!onleft(p[last-1],q[first]))last--;
	if(last-first<=1)return 0;
	p[last]=getsec(q[last].p,q[last].v,q[first].p,q[first].v);
	double ans=0;
	for(int i=first;i<last;i++)ans+=cross(p[i]-p[first],p[i+1]-p[first]); 
	ans=0.5*fabs(ans);
	return ans;
}
int n;
void init()
{
	double x1=x[1],y1=y[1];
	double x2=x[2],y2=y[2];
	cnt=0;
	for(int i=2;i<=n;i++)
	{
		double x3=x[i],y3=y[i];
		double x4=x[i+1],y4=y[i+1];
		double a,b,c;
		//手推(y1+y4-y2-y3)x+(x2+x3-x1-x4)y+(x1y2-x2y1+x4y3-x3y4)<0
		a=y1+y4-y2-y3;
		b=x2+x3-x1-x4;
		c=x1*y2-x2*y1+x4*y3-x3*y4;
		//(-b,a)   ax+by+c<0
		++cnt;
		point v,p;
		v=point(-b,a);
		if(dcmp(b)!=0)p=point(0,-c/b);
		else p=point(-c/a,0);
		l[cnt]=line(p,v);
	}
	++cnt;
	l[cnt]=line(point(x[1],y[1]),point(x2-x1,y2-y1));
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&x[i],&y[i]);
	}
	x[n+1]=x[1];
	y[n+1]=y[1];
	double ans1=0;
	for(int i=1;i<n;i++)
	{
		ans1+=cross(point(x[i]-x[1],y[i]-y[1]),point(x[i+1]-x[1],y[i+1]-y[1]));
	}
	ans1=0.5*fabs(ans1);
	init();
	double ans2=hp(l,cnt);
	printf("%.4f\n",ans2/ans1);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值