Uvalive 3890 Most Distant Point from the Sea(半平面交+二分)

来源:互联网 发布:乒乓球入门知乎 编辑:程序博客网 时间:2024/06/06 04:49

题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1891

思路:

1.求一点到凸包边界最远,即求最大内切圆半径。

2.二分半径r,讲凸包上边像内平移(点p+(normal vector)*r,方向向量v),求半平面交。若交点大于0,此时半径仍可扩大(即所求圆并未与边相切)。若交点等于0,则此时可能存在一内切圆,继续缩小半径。

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const double eps=1e-6;const double PI=acos(-1.0);const int maxn=200;struct Point{    double x,y;    Point() {}    Point(double x,double y):x(x),y(y) {}    void read()    {        scanf("%lf%lf",&x,&y);    }};typedef Point Vector;Vector operator - (Vector A,Vector B){    return Vector(A.x-B.x,A.y-B.y);}Vector operator + (Vector A,Vector B){    return Vector(A.x+B.x,A.y+B.y);}Vector operator * (Vector A,double t){    return Vector(A.x*t,A.y*t);}double Cross(Vector A,Vector B){    return A.x*B.y-A.y*B.x;}int dcmp(double x){    if(fabs(x)<eps) return 0;    else return x<0?-1:1;}double Dot(Vector A,Vector B){  return A.x*B.x+A.y*B.y;}double Length(Vector A){  return sqrt(Dot(A,A));}Vector Normal(Vector A){  double L=Length(A);  return Vector(-A.y/L,A.x/L);}struct Line{    Point P;    Vector v;    double ang;    Line() {}    Line(Point p,Vector v):P(p),v(v)    {        ang=atan2(v.y,v.x);    }    bool operator < (const Line& L) const    {        return ang<L.ang;    }    Line Move(double d)    {        Vector tmp=Normal(v);        return Line(P+tmp*d,v);    }};bool onLeft(Line L,Point p){    return Cross(L.v,p-L.P)>0;}Point getIntersection(Line a,Line b){    Vector u=a.P-b.P;    double t=Cross(b.v,u)/Cross(a.v,b.v);    return a.P+a.v*t;}int Half_Plane_Intersection(Line* L,int n,Point* poly){    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]);    int m=0;    for(int i=first; i<=last; i++)        poly[m++]=p[i];    return m;}int n;Line l[maxn];Point p[maxn];int check(double r){    for(int i=0; i<n; i++)    {        Vector v=Normal(p[(i+1)%n]-p[i]);        l[i]=Line(p[i],p[(i+1)%n]-p[i]).Move(r);    }    Point poly[maxn];    return Half_Plane_Intersection(l,n,poly)==0;}double solve(){    double L=0,R=20000,ans;    while(dcmp(R-L)!=0)    {        double mid=(L+R)/2;        if(check(mid))        {            ans=mid;            R=mid;        }        else        {            L=mid;        }    }    return ans;}int main(){#ifdef debu    freopen("in.txt","r",stdin);#endif // debug    while(scanf("%d",&n)!=EOF&&n)    {        for(int i=0; i<n; i++) p[i].read();        printf("%.6f\n",solve());    }    return 0;}






阅读全文
0 0
原创粉丝点击