题目链接: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;
}