SGU332

竟然花了一天的时间才过了这道几何题……

说下题意。给一个n边的凸多边形,保证给出的数据没有三点共线,求这个多边形能包含的最大圆的半径。

开始时完全搞错方向,甚至想了个把各个顶点的移动速度算出来的方法,结果发现根本行不通……正确的思路应该是二分半径,然后每次求一次半平面交判是否交集为空。其实乱搞速度的过程中想到了这个,但有点怀疑复杂度不够,SGU才给了0.25s的时限,复杂度还要nlogn乘一个感觉蛮大的常数……后来实在水不出来了就照这个思路敲了红书的模板,结果不知是敲错哪里来了个RTE……换了白书的模板才终于AC……

这A题的效率也是醉了……

#include<stdio.h>
#include<vector>
#include<deque>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<complex>
using namespace std;
const double eps=1e-8;
struct point
{
	double x,y;
	point(double xt=0,double yt=0):x(xt),y(yt) {}
};
double cross(point a,point b){return a.x*b.y-a.y*b.x;}
point operator +(point a,point b) {return point(a.x+b.x,a.y+b.y);}
point operator -(point a,point b) {return point(a.x-b.x,a.y-b.y);}
point operator *(point a,double b) {return point(a.x*b,a.y*b);}
point operator /(point a,double b) {return point(a.x/b,a.y/b);}
struct line
{
	point p,v;
	double ang;
	line(){}
	line(point pt,point vt):p(pt),v(vt){ang=atan2(v.y,v.x);}
	bool operator<(const line& l)const
	{
		return ang<l.ang;
	}
};
bool onleft(line l,point p)
{
	return cross(l.v,p-l.p)>0;
}
point getintersection(line a,line b)
{
	point u=a.p-b.p;
	double t=cross(b.v,u)/cross(a.v,b.v);
	return a.p+a.v*t;
}
int halfplaneintersection(line *l,int n)
{
	sort(l,l+n);
	int first,last;
	point *p=new point[n];
	line *q=new line[n];
	q[first=last=0]=l[0];
	for(int i=1;i<n;i++)
	{
		while(first<last&&!onleft(l[i],p[last-1])) --last;
		while(first<last&&!onleft(l[i],p[first])) ++first;
		q[++last]=l[i];
		if(fabs(cross(q[last].v,q[last-1].v))<eps)
		{
			last--;
			if(onleft(q[last],l[i].p)) q[last]=l[i];
		}
		if(first<last) p[last-1]=getintersection(q[last-1],q[last]);
	}
	while(first<last&&!onleft(q[first],p[last-1])) --last;
	if(last-first<=1) return 0;
	p[last]=getintersection(q[last],q[first]);
	return last-first+1;
}
double length(point a)
{
	return sqrt(a.x*a.x+a.y*a.y);
}
point normal(point a)
{
	double le=length(a);
	return point(-a.y/le,a.x/le);
}

int n;
point po[10005],nl[10005];
line lo[10005],lt[10005];
point re[10005];

int main()
{
	int i,j;
	scanf("%d",&n);
	for(i=0;i<n;i++) scanf("%lf %lf",&po[i].x,&po[i].y);
	for(i=0;i<n;i++) {lo[i]=line(po[i],po[(i+1)%n]-po[i]);nl[i]=normal(po[(i+1)%n]-po[i]);}
	double at=0,bt=2e7+10;
	while(bt-at>1e-6)
	{
		double xt=(at+bt)/2;
		for(i=0;i<n;i++) lt[i]=line(po[i]+nl[i]*xt,po[(i+1)%n]-po[i]);
		int m=halfplaneintersection(lt,n);
		if(m<=1) bt=xt;
		else at=xt;
	}
	printf("%.5lf\n",(at+bt)/2);
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值