poj3525 Most Distant Point from the Sea 发表于 2016-12-28 | 更新于 2018-06-18 LinkSolution找一个半径最大的内切圆。 二分r,将凸包上的边向内移动,求半平面交看是否为空。 移动边的时候比较巧妙,用到了单位法向量。 Code123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131//Code by Lucida#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define red(x) scanf("%d",&x)#define fred(x) scanf("%lf",&x)template <class T> inline bool chkmx(T &a,const T &b){return a<b?a=b,1:0;}template <class T> inline bool chkmn(T &a,const T &b){return a>b?a=b,1:0;}const int MAXN=100+1;typedef double ld;using std::sort;const ld eps=1e-7,undefined=1e250,pi=acos(-1.0);int fcmp(ld x){ if(-eps<x && x<eps) return 0; return x<0?-1:1;}template <class T> T sqr(T x){return x*x;}template <class T> T abs(T x){return x>0?x:-x;}struct vec{ ld x,y; vec(ld _x=0,ld _y=0):x(_x),y(_y){} vec operator -(){return vec(-x,-y);} ld norm(){return sqrt(x*x+y*y);} bool operator <(vec a) { if(x!=a.x) return x<a.x; return y<a.y; } void operator +=(vec a){x+=a.x,y+=a.y;} void operator -=(vec a){x-=a.x,y-=a.y;} void operator /=(ld a){x/=a,y/=a;} void operator *=(ld a){x*=a,y*=a;} bool operator ==(vec a){return x==a.x && y==a.y;}};typedef vec point;vec operator +(vec a,vec b){return vec(a.x+b.x,a.y+b.y);}vec operator -(vec a,vec b){return vec(a.x-b.x,a.y-b.y);}vec operator *(vec a,ld t){return vec(a.x*t,a.y*t);}vec operator /(vec a,ld t){return vec(a.x/t,a.y/t);}ld inner(vec a,vec b){return a.x*b.x+a.y*b.y;}ld outer(vec a,vec b){return a.x*b.y-a.y*b.x;}vec rotate(vec a,ld rad){return vec(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));}struct line{ point a;vec v; ld angle; line(){} line(point _a,vec _v):a(_a),v(_v){angle=atan2(v.y,v.x);} vec norm() { vec normal=rotate(v,pi/2); normal/=normal.norm(); return normal; } bool operator<(const line &a)const {return angle<a.angle;}}il[MAXN];bool onleft(point a,line l){return fcmp(outer(l.v,a-l.a))>=0;}//在左或者在上bool parl(line a,line b){return fcmp(outer(a.v,b.v))==0;}point cross(line l1,line l2){ vec v=l1.a-l2.a; ld t=outer(v,l2.v)/outer(l2.v,l1.v); return l1.a+l1.v*t;}int n;int intersect(line *l,point *tio){ sort(l+1,l+1+n); static point Qp[MAXN]; static line Ql[MAXN]; int head=1,tail=0; Ql[++tail]=l[1]; #define count(x,y) (y-x+1) for(int i=2;i<=n;i++) { while(count(head,tail)>=2 && !onleft(Qp[tail-1],l[i])) tail--; while(count(head,tail)>=2 && !onleft(Qp[head],l[i])) head++; Ql[++tail]=l[i]; if(parl(Ql[tail-1],Ql[tail])) { tail--; if(onleft(l[i].a,Ql[tail])) Ql[tail]=l[i]; } if(count(head,tail)>=2) Qp[tail-1]=cross(Ql[tail-1],Ql[tail]); } while(count(head,tail)>=2 && !onleft(Qp[tail-1],Ql[head])) tail--; if(count(head,tail)<2) return 0; Qp[tail]=cross(Ql[head],Ql[tail]); int tol=0; for(int i=head;i<=tail;i++) tio[++tol]=Qp[i]; return tol; #undef count}bool check(ld r){ static line tr[MAXN]; for(int i=1;i<=n;i++) tr[i]=il[i]; for(int i=1;i<=n;i++) tr[i].a+=tr[i].norm()*r; static point tio[MAXN]; int tol=intersect(tr,tio); return tol>2;}void WORK(){ static point p[MAXN]; for(int i=1;i<=n;i++) fred(p[i].x),fred(p[i].y); for(int i=1;i<=n;i++) il[i]=line(p[i],p[i+1>n?1:i+1]-p[i]); ld L=0,R=1e10; while(fcmp(R-L)) { ld MID=(L+R)/2; if(check(MID)) L=MID; else R=MID; } printf("%.7lf\n",L);}int main(){ freopen("input","r",stdin); while(red(n),n) WORK(); return 0;}