提议:海中一个凸多边形小岛,求出岛上离海最远点到海的距离。
思路:就是求这个凸多边形内切圆的最大半径。对半径进行二分,将多边形所有边向内平移半径的长度,然后求半平面交,如果有交则有满足的点。
在poj上用g++交wa了,c++又过了。。。坑
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn=200; const double eps=1e-8; struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y) {} }; typedef Point Vector; struct DLine { Point P; Vector v; double ang; DLine() {} DLine(Point P,Vector v):P(P),v(v) { ang=atan2(v.y,v.x); } bool operator < (const DLine& L) const { return ang<L.ang; } }; 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); } 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 Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } Vector Normal(Vector A)//向量的单位法线,即左转90度 { double L=Length(A); return Vector(-A.y/L,A.x/L); } bool OnLeft(DLine L,Point p) { return Cross(L.v,p-L.P)>0; } Point GetIntersection(DLine a,DLine 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 HalfPlaneIntersection(DLine* L,int n){ sort(L,L+n); int first,last; Point *p=new Point[n]; DLine *q=new DLine[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]); return (last-first+1); } int n; Point p[maxn]; DLine l[maxn]; Vector v[maxn],v2[maxn]; void solve() { double left=0,right=10000;//二分 while(right-left>1e-6) { double mid=left+(right-left)/2; for(int i=0; i<n; i++) l[i]=DLine(p[i]+v2[i]*mid,v[i]); int m=HalfPlaneIntersection(l,n); if(!m) right=mid; else left=mid; } printf("%.6lf ",left); } int main() { // freopen("in.cpp","r",stdin); while(scanf("%d",&n) && n) { for(int i=0; i<n; i++) scanf("%lf%lf",&p[i].x,&p[i].y); for(int i=0; i<n; i++) { v[i]=p[(i+1)%n]-p[i]; v2[i]=Normal(v[i]); } solve(); } return 0; }