【POJ3525】Most Distant Point from the Sea-半平面交+二分答案
测试地址:Most Distant Point from the Sea
题目大意:给定一个凸多边形,求凸多边形内某点到各边的最小距离的最大值。
做法:本题需要用到半平面交+二分答案。
首先答案显然具有单调性,所以我们二分答案,转化成判定性问题。
考虑答案,我们只要将构成原凸多边形的半平面都向内缩个单位长度,然后判定半平面交存不存在即可。因为不用排序,所以时间复杂度为,配上外面的二分就多个。
以下是本人代码:
#include <bits/stdc++.h>
#define eps 1e-12
using namespace std;
int n,bot,top;
struct Point
{
double x,y;
}p[110],zero;
struct Line
{
Point a,b;
}l[110],q[110];
Point operator - (Point a,Point b)
{
Point s={a.x-b.x,a.y-b.y};
return s;
}
double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double multi(Point a,Point b)
{
return a.x*b.y-b.x*a.y;
}
Point inter(Line a,Line b)
{
double a1=multi(b.b-a.a,b.a-a.a),a2=multi(b.a-a.b,b.b-a.b);
Point s={(a2*a.a.x+a1*a.b.x)/(a2+a1),(a2*a.a.y+a1*a.b.y)/(a2+a1)};
return s;
}
bool JudgeOut(Point a,Line b)
{
return multi(a-b.a,b.b-b.a)>0.0;
}
bool solve()
{
q[1]=l[1],q[2]=l[2],bot=1,top=2;
for(int i=3;i<=n;i++)
{
while (bot<top&&JudgeOut(inter(q[top-1],q[top]),l[i])) top--;
while (bot<top&&JudgeOut(inter(q[bot],q[bot+1]),l[i])) bot++;
q[++top]=l[i];
}
while (bot<top&&JudgeOut(inter(q[top-1],q[top]),q[bot])) top--;
while (bot<top&&JudgeOut(inter(q[bot],q[bot+1]),q[top])) bot++;
return top-bot>1;
}
int main()
{
zero.x=zero.y=0.0;
while(scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
p[n+1]=p[1];
double lft=0.0,rht=10000.0;
while (rht-lft>eps)
{
double mid=(lft+rht)/2.0;
for(int i=1;i<=n;i++)
{
l[i].a.x=p[i].y-p[i+1].y,l[i].a.y=p[i+1].x-p[i].x;
double r=mid/dis(zero,l[i].a);
l[i].a.x*=r,l[i].a.y*=r;
l[i].a.x+=p[i].x,l[i].a.y+=p[i].y;
l[i].b.x=l[i].a.x+p[i+1].x-p[i].x;
l[i].b.y=l[i].a.y+p[i+1].y-p[i].y;
}
if (solve()) lft=mid;
else rht=mid;
}
printf("%.6f\n",lft);
}
return 0;
}