题目:https://vjudge.net/problem/UVALive-3890
二分法,通过收缩凸边型,直到半平面交为空集。
#include<bits/stdc++.h>
using namespace std;
#include<bits/stdc++.h>
using namespace std;
struct Point{
double x,y;
Point(double x=0,double y=0) :x(x),y(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 p){return Vector(A.x*p,A.y*p);}
Vector operator /(Vector A,double p){return Vector(A.x/p,A.y/p);}
bool operator <(const Point& a,const Point &b){
return a.x<b.x || (a.x==b.x && a.y<b.y);
}
const double eps=1e-10;
int dcmp(double x){
if(fabs(x)<eps) return 0;else return x<0?-1 :1;
}
bool operator == (const Point &a,const Point &b){
return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;}
double dot(Vector A,Vector B){
return A.x*B.x+A.y*B.y;
}
double length(Vector A){return sqrt(dot(A,A));}
double angle(Vector A,Vector B){
return acos(dot(A,B)/length(A)/length(B));
}
Vector rotate(Vector A,double rad){ //rad正数时表示逆时针 负数时表示顺时针
return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
double cross(Vector A,Vector B){
return A.x*B.y-A.y*B.x;
}
Vector normal(Vector A){
double l=length(A);
return Vector(-A.y/l,A.x/l);
}
struct Line{
Point p;
Vector v;
Line(){}
Line(Point p,Vector v) :p(p),v(v){}
Point point(double t){return p+v*t;}
};
bool onleft(Line l,Point p){
return cross(l.v,p-l.p)>0;
}
double getangle(Vector a){
return atan2(a.y,a.x);
}
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;
}
bool cmp(Line a,Line b){
double c=getangle(a.v),d=getangle(b.v);
return c<d ? 1:0;
}
Line l[200];
int halfplaneintersection(Line *l,int n,Point *poly){
sort(l,l+n,cmp);
int first,last;
Point *p=new Point[n]; //p[i]为 q[i]和q[i+1]的交点
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;
}
Point p[200],poly[200];
Vector v[200],v2[200];
int main(){
int n;
while(scanf("%d",&n)==1 && n){
int m,x,y;
for(int i=0;i<n;i++){scanf("%d%d",&x,&y); p[i]=Point(x,y);}
for(int i=0;i<n;i++){
v[i]=p[(i+1)%n]-p[i];
v2[i]=normal(v[i]);
}
double left=0,right=20000;
while(right-left>1e-6){
double mid=left+(right-left)/2;
for(int i=0;i<n;i++) l[i]=Line(p[i]+v2[i]*mid,v[i]);
m=halfplaneintersection(l,n,poly);
if(!m) right=mid;else left=mid;
}
printf("%.6lf\n",left);
}
return 0;
}