有一个海岛,求海岛上距离海岸线最远的点。lrj白皮书例题,我这里也有介绍半平面交的相关知识。直接求不好求,于是二分这个距离,把海岸线向”里”(逆时针给出边的时候左边为里,也就是它对应的半平面)移动这个距离,如果这些半平面有交集,则说明距离不够远,如果没有交集则说明距离太远。于是二分到恰好没有交集。
#include<cstdio>
#include<cmath>
#include<algorithm>
#define MAXN 110
using namespace std;
struct poi
{
double x,y;
poi(double x = 0,double y = 0) :x(x),y(y) {}
}pos[MAXN],a[MAXN],out[MAXN],v1[MAXN],v2[MAXN];
typedef poi vec;
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,double p) {return vec(A.x*p, A.y*p);}
const double eps = 1e-7;
int dcmp(double x)
{
if(fabs(x) < eps) return 0;
else return x>0?1:-1;
}
bool operator <(vec A, vec B)
{
if(A.x == B.x) return A.y < B.y;
else return A.x < B.x;
}
double cross(vec A,vec B) {return A.x*B.y - A.y*B.x;}
double dot(vec A,vec B) {return A.x*B.x + A.y*B.y;}
double length(vec A) {return sqrt(dot(A,A));}
vec normal(vec A) {double L = length(A); return vec(-A.y/L, A.x/L);}
struct Line
{
poi p; vec v;
double ang;
Line(){}
Line(poi p,vec v) :p(p),v(v) {ang = atan2(v.y,v.x);}
bool operator <(const Line &b)const{return ang < b.ang;}
}L[MAXN],Q[MAXN];
bool Onleft(Line A,poi p) {return cross(A.v, p-A.p) > 0;}
poi GetLineIntersection(Line A,Line B)
{
double t = cross(B.v, A.p-B.p) /cross(A.v, B.v);
return A.p + A.v*t;
}
int HalfplaneIntersection(int n)
{
sort(L,L+n);
int head = 0,tail = 0;
Q[0] = L[0];
for(int i = 0; i < n; i++)
{
while(head < tail&& !Onleft(L[i], a[tail-1])) --tail;
while(head < tail&& !Onleft(L[i], a[head])) ++head;
Q[++tail] = L[i];
if(fabs(cross(Q[tail].v,Q[tail-1].v)) < eps){
tail--;
if(Onleft(Q[tail], L[i].p)) Q[tail] = L[i];
}
if(head < tail) a[tail-1] = GetLineIntersection(Q[tail], Q[tail-1]);
}
while(head < tail&& !Onleft(Q[head], a[tail-1])) --tail;
if(tail - head <= 1) return 0;
a[tail] = GetLineIntersection(Q[head], Q[tail]);
int m = 0;
for(int i = head; i <= tail; i++) out[m++] = a[i];
return m;
}
int main()
{
int n;
while(scanf("%d",&n) != EOF&&n)
{
for(int i = 0; i < n; i++) scanf("%lf%lf",&pos[i].x,&pos[i].y);
for(int i = 0; i < n; i++)
{
v1[i] = pos[(i+1)%n] - pos[i];
v2[i] = normal(v1[i]);
}
double l = 0, r = 20000, mid;
while(r-l > eps)
{
mid = (l+r)/2;
for(int i = 0; i < n; i++) L[i] = Line(pos[i] + v2[i]*mid, v1[i]);
int m = HalfplaneIntersection(n);
if(!m) r = mid; else l = mid;
}
printf("%.6lf\n",l);
}
}