省选专练[ZJOI2008]瞭望塔

9 篇文章 0 订阅
3 篇文章 0 订阅

模板

能够满足条件的一定出自核是吧

于是咱跑个半平面交。

答案出自跑出来的凸壳的顶点上。

#include<bits/stdc++.h>
using namespace std;
const double INF=1e16;
const double eps=1e-8;
const int N=20000;
int n;
double ans=INF;
int cmp(double x){
	if(fabs(x)<eps)
		return 0;
	return x>eps?1:-1;
}
bool equal(double x,double y){
	return cmp(x-y)==0;
}
struct Point{
	double x;
	double y;
	Point(double _x=0,double _y=0):x(_x),y(_y){}
	friend Point operator + (Point A,Point B){return Point(A.x+B.x,A.y+B.y);}
	friend Point operator - (Point A,Point B){return Point(A.x-B.x,A.y-B.y);}
	friend Point operator * (Point A,double B){return Point(A.x*B,A.y*B);}
	friend Point operator / (Point A,double B){return Point(A.x/B,A.y/B);}
	double ang(){return atan2(y,x);}
	void read(){scanf("%lf%lf",&x,&y);}
}p[N],a[N];
typedef Point Vector;
double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
struct Line{
	Point p;
	Vector v;
	double Ang;
	Line(Point _p=Point(0,0),Vector _v=Vector(0,0)):p(_p),v(_v){}
	double ang(){return v.ang();}
}l[N],temp[N],convex_hull[N];
bool comp(Line A,Line B){return A.Ang<B.Ang;}
Point getpot(Line A,Line B){
	return B.p+B.v*(Cross(A.v,A.p-B.p)/Cross(A.v,B.v));
}
bool in(Point p,Line l){
	return cmp(Cross(l.v,p-l.p))>=0;
}
/*int cmp(double x){
	if(fabs(x)<=eps){
		return 0;
	}
	else{
		return x>0?1:1;
	}
}
bool equal(double x,double y){
	return (cmp(x-y)==0);
}
struct Point {
	double x,y;
	Point(double _x=0,double _y=0):x(_x),y(_y){}
	friend Point operator + (Point A,Point B){return Point(A.x+B.x,A.y+B.y);}
	friend Point operator - (Point A,Point B){return Point(A.x-B.y,A.y-B.y);}
	friend Point operator * (Point A,double k){return Point(A.x*k,A.y*k);}
	friend Point operator / (Point A,double k){return Point(A.x/k,A.y/k);}
	double ang(){return (atan2(y,x));}
	void read(){scanf("%lf%lf",&x,&y);}
}p[N],a[N];
typedef Point Vector;
double Cross(Vector A,Vector B){
	return A.x*B.y-A.y*B.x;
}
double Dot(Vector A,Vector B){
	return A.x*B.x+A.y*B.y;
}
struct Line{
	Point p;
	Vector v;
	Line(Point _p=(Point(0,0)),Vector _v=(Vector(0,0))):p(_p),v(_v){}
	double Ang;
	double ang(){
		return v.ang();
	}
}l[N],convex_hull[N],temp[N];
bool comp(Line A,Line B){
	return A.Ang<B.Ang;
}
Point getpot(Line A,Line B){
	return B.p+B.v*(Cross(A.v,A.p-B.p)/Cross(A.v,B.v));
}
bool in(Point p,Line l){
	return cmp(Cross(l.v,p-l.p))>=0;
}*/
int lcnt=0,tot=0;
/*void Shrink(Line *A,int &num){
	int siz=0;
	for(int i=1;i<=num;i++){
		if(!siz){
			siz++;
			temp[siz]=A[i];
		}
		else{
			if(!equal(A[i].Ang,temp[siz].Ang)){
				siz++;
				temp[siz]=A[i];
			}
			else{
				if(in(A[i].p,temp[siz])){
					temp[siz]=A[i];
				}
			}
		}
	}
	num=siz;
	for(int i=1;i<=siz;i++){
		A[i]=temp[i];
	}
}*/
void pre(){
	p[0].x=p[1].x;
	p[0].y=INF;
	p[n+1].x=p[n].x;
	p[n+1].y=INF;
	for(int i=1;i<=n;i++)
	{
		l[++lcnt].p=p[i-1];
		l[lcnt].v=p[i]-p[i-1];
		l[++lcnt].p=p[i];
		l[lcnt].v=p[i+1]-p[i];
	}
	for(int i=1;i<=lcnt;i++){
		l[i].Ang=l[i].ang();
	}
	sort(l+1,l+1+lcnt,comp);
}
bool hpi(){
	int head=1;
	int tail=2;
	convex_hull[1]=l[1];
	convex_hull[2]=l[2];
	for(int i=3;i<=lcnt;i++){
		while(head<tail && !(in(getpot(convex_hull[tail],convex_hull[tail-1]),l[i])))tail--;
		while(head<tail && !(in(getpot(convex_hull[head],convex_hull[head+1]),l[i])))head++;
		convex_hull[++tail]=l[i];
	}
	while(head<tail && !in(getpot(convex_hull[tail],convex_hull[tail-1]),convex_hull[head]))tail--;
//	int head=1;
//	int tail=2;
//	convex_hull[1]=l[1];
//	convex_hull[2]=l[2];
//	for(int i=3;i<=lcnt;i++){
//		while(head<tail&&!(in(getpot(convex_hull[tail],convex_hull[tail-1]),l[i])))tail--;
//		while(head<tail&&!(in(getpot(convex_hull[head],convex_hull[head+1]),l[i])))head++;
//		convex_hull[++head]=l[i];
//	}
//	while(head<tail&&!in(getpot(convex_hull[tail],convex_hull[tail-1]),convex_hull[head]))head++;
	for(int i=head;i<tail;i++){
		a[++tot]=getpot(convex_hull[i],convex_hull[i+1]);
	}
//	cout<<tot<<endl;
}
void getans()
{
	for(int k=1;k<=tot;k++)
		for(int i=1;i<n;i++)
		{
			Point t;t.x=a[k].x;t.y=-1;
			if(a[k].x>=p[i].x&&a[k].x<=p[i+1].x)
			    ans=min(ans,a[k].y-getpot((Line){p[i],p[i+1]-p[i]},(Line){t,a[k]-t}).y);
		}
	for(int k=1;k<=n;k++)
		for(int i=1;i<tot;i++)
		{
			Point t;t.x=p[k].x;t.y=-1;
			if(p[k].x>=a[i].x&&p[k].x<=a[i+1].x)
			    ans=min(ans,getpot((Line){a[i],a[i+1]-a[i]},(Line){t,p[k]-t}).y-p[k].y);
		}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lf",&p[i].x);
	} 
	for(int i=1;i<=n;i++){
		scanf("%lf",&p[i].y);
	}
	pre();
	hpi();
	getans();
	if(fabs(ans)<=eps)
		ans=0;
	printf("%.3lf",ans);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值