SGU 332 Largest Circle(凸包内接圆半径nlogn)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=332

题意:逆时针给出一个凸包,给凸包的最大内接圆半径。

思路:nlogn的算法:

(1)二分内切圆半径的值R

(2)把每个半平面向内平移R的长度

(3)使用一个双端队列(deque),依次向首部加入hplane[0],hplane[1],

     for(i=2;i<num_hplane;i++)

     {

              while(deque顶端的两个半平面的交点在hplane[i]外)  删除deque顶端

              while(deque底部的两个半平面的交点在hplane[i]外)  删除deque底部

              将hplane[i]加入deque顶端

     }

     while(deque顶端的两个半平面的交点在底部半平面外) 删除deque顶端

     while(deque底部的两个半平面的交点在顶端半平面外) 删除deque底部

     判断最后剩下的半平面是否在3个以上

#include <iostream>

#include <cstdio>

#include <string.h>

#include <algorithm>

#include <cmath>

#include <vector>

#include <queue>

#include <set>

#include <stack>

#include <string>

#include <map>





#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)>=0?(x):-(x))

#define i64 long long

#define u32 unsigned int

#define u64 unsigned long long

#define clr(x,y) memset(x,y,sizeof(x))

#define CLR(x) x.clear()

#define ph(x) push(x)

#define pb(x) push_back(x)

#define Len(x) x.length()

#define SZ(x) x.size()

#define PI acos(-1.0)

#define sqr(x) ((x)*(x))

#define MP(x,y) make_pair(x,y)

#define EPS 1e-5



#define FOR0(i,x) for(i=0;i<x;i++)

#define FOR1(i,x) for(i=1;i<=x;i++)

#define FOR(i,a,b) for(i=a;i<=b;i++)

#define DOW0(i,x) for(i=x;i>=0;i--)

#define DOW1(i,x) for(i=x;i>=1;i--)

#define DOW(i,a,b) for(i=a;i>=b;i--)

using namespace std;





void RD(int &x){scanf("%d",&x);}

void RD(i64 &x){scanf("%I64d",&x);}

void RD(u32 &x){scanf("%u",&x);}

void RD(double &x){scanf("%lf",&x);}

void RD(int &x,int &y){scanf("%d%d",&x,&y);}

void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}

void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}

void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}

void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}

void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}

void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}

void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}

void RD(char &x){x=getchar();}

void RD(char *s){scanf("%s",s);}

void RD(string &s){cin>>s;}





void PR(int x) {printf("%d\n",x);}

void PR(i64 x) {printf("%I64d\n",x);}

void PR(u32 x) {printf("%u\n",x);}

void PR(double x) {printf("%.6lf\n",x);}

void PR(char x) {printf("%c\n",x);}

void PR(char *x) {printf("%s\n",x);}

void PR(string x) {cout<<x<<endl;}



const int N=10005;



int DB(double x)

{

    if(x>EPS) return 1;

    if(x<-EPS) return -1;

    return 0;

}



class point

{

public:

    double x,y;



    point(){}

    point(double _x,double _y)

    {

        x=_x;

        y=_y;

    }



    point operator+(point a)

    {

        return point(x+a.x,y+a.y);

    }



    point operator-(point a)

    {

        return point(x-a.x,y-a.y);

    }



    double operator*(point a)

    {

        return x*a.y-y*a.x;

    }



    point operator*(double t)

    {

        return point(x*t,y*t);

    }



    double operator^(point a)

    {

        return x*a.x+y*a.y;

    }



    point operator/(double t)

    {

        return point(x/t,y/t);

    }



    double getLen()

    {

        return sqrt(x*x+y*y);

    }



    void get()

    {

        RD(x,y);

    }



    int operator==(point a)

    {

        return DB(x-a.x)==0&&DB(y-a.y)==0;

    }



    int operator<(point a)

    {

        if(DB(x-a.x)) return x<a.x;

        return y<a.y;

    }



    point adjust(double L)

    {

        double temp=getLen();

        return point(x*L/temp,y*L/temp);

    }



    void print()

    {

        printf("%.6lf %.6lf\n",x,y);

    }

};





class Vector

{

public:

    point s,t;

    double ang;



    Vector(){}

    Vector(point _s,point _t)

    {

        s=_s;

        t=_t;

        ang=atan2(t.y-s.y,t.x-s.x);

    }



};



Vector a[N],b[N],st[N];

point p[N];

int n;





double cross(point a,point b,point p)

{

    return (b-a)*(p-a);

}



int in(point p,Vector a)

{

    return cross(a.s,a.t,p)>0;

}



point getCross(Vector a,Vector b)

{

    double s1=(a.s-b.s)*(a.t-b.s);

    double s2=(a.t-b.t)*(a.s-b.t);

    return (b.s*s2+b.t*s1)/(s1+s2);

}





Vector move(Vector a,double L)

{

    point d=point(a.s.y-a.t.y,a.t.x-a.s.x);

    d=d.adjust(L);

    return Vector(a.s+d,a.t+d);

}



int cmp(Vector a,Vector b)

{

    return a.ang<b.ang;

}





int OK(double L)

{

    int i;

    FOR1(i,n) b[i]=move(a[i],L);

    int head=1,tail=1;

    st[1]=b[1];

    for(i=2;i<=n;i++)

    {

        while(tail>head&&!in(getCross(st[tail-1],st[tail]),b[i])) tail--;

        while(tail>head&&!in(getCross(st[head],st[head+1]),b[i])) head++;

        st[++tail]=b[i];

    }

    while(tail>head&&!in(getCross(st[tail],st[tail-1]),st[head])) tail--;

    while(tail>head&&!in(getCross(st[head],st[head+1]),st[tail])) head++;

    return tail>head+1;

}





int main()

{

    RD(n);

    int i;

    FOR1(i,n) p[i].get();

    p[0]=p[n];

    FOR1(i,n) a[i]=Vector(p[i-1],p[i]);

    double low=0,high=1e8,mid;

    while(DB(low-high)==-1)

    {

        mid=(low+high)/2;

        if(OK(mid)) low=mid;

        else high=mid;

    }

    PR(mid);

    return 0;

}

  

你可能感兴趣的:(log)