POJ3525 Most Distant Point from the Sea(半平面交)

时间:2021-12-26 12:56:32

给你一个凸多边形,问在里面距离凸边形最远的点。

方法就是二分这个距离,然后将对应的半平面沿着法向平移这个距离,然后判断是否交集为空,为空说明这个距离太大了,否则太小了,二分即可。

#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <string>
#include <algorithm>
using namespace std; #define maxn 2500
#define eps 1e-7 int n; int dcmp(double x){
return (x > eps) - (x < -eps);
} struct Point
{
double x, y;
Point(){}
Point(double _x, double _y) :x(_x), y(_y){}
Point operator + (const Point &b) const{
return Point(x + b.x, y + b.y);
}
Point operator - (const Point &b) const{
return Point(x - b.x, y - b.y);
}
Point operator *(double d) const{
return Point(x*d, y*d);
}
Point operator /(double d) const{
return Point(x / d, y / d);
}
double det(const Point &b) const{
return x*b.y - y*b.x;
}
double dot(const Point &b) const{
return x*b.x + y*b.y;
}
Point rot90(){
return Point(-y, x);
}
Point norm(){
double len=sqrt(this->dot(*this));
return Point(x, y) / len;
}
void read(){
scanf("%lf%lf", &x, &y);
}
}; #define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) (dcmp(cross(p1,p2,p3))) Point isSS(Point p1, Point p2, Point q1, Point q2){
double a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
return (p1*a2 + p2*a1) / (a1 + a2);
} struct Border
{
Point p1, p2;
double alpha;
void setAlpha(){
alpha = atan2(p2.y - p1.y, p2.x - p1.x);
}
}; bool operator < (const Border &a,const Border &b) {
int c = dcmp(a.alpha - b.alpha);
if (c != 0) {
return c == 1;
}
else {
return crossOp(b.p1, b.p2, a.p1) > 0;
}
} bool operator == (const Border &a, const Border &b){
return dcmp(a.alpha - b.alpha) == 0;
} Point isBorder(const Border &a, const Border &b){
return isSS(a.p1, a.p2, b.p1, b.p2);
} Border border[maxn];
Border que[maxn];
int qh, qt;
// check函数判断的是新加的半平面和由a,b两个半平面产生的交点的方向,若在半平面的左侧返回True
bool check(const Border &a, const Border &b, const Border &me){
Point is = isBorder(a, b);
return crossOp(me.p1, me.p2, is) > 0;
} bool convexIntersection()
{
qh = qt = 0;
sort(border, border + n);
n = unique(border, border + n) - border;
for (int i = 0; i < n; i++){
Border cur = border[i];
while (qh + 1 < qt&&!check(que[qt - 2], que[qt - 1], cur)) --qt;
while (qh + 1 < qt&&!check(que[qh], que[qh + 1], cur)) ++qh;
que[qt++] = cur;
}
while (qh + 1 < qt&&!check(que[qt - 2], que[qt - 1], que[qh])) --qt;
while (qh + 1 < qt&&!check(que[qh], que[qh + 1], que[qt - 1])) ++qh;
return qt - qh > 2;
} Point ps[maxn]; bool judge(double x)
{
for (int i = 0; i < n; i++){
border[i].p1 = ps[i];
border[i].p2 = ps[(i + 1) % n];
}
for (int i = 0; i < n; i++){
Point vec = border[i].p2 - border[i].p1;
vec=vec.rot90().norm();
vec = vec*x;
border[i].p1 = border[i].p1 + vec;
border[i].p2 = border[i].p2 + vec;
border[i].setAlpha();
}
return convexIntersection();
} int main()
{
while (cin>>n&&n)
{
for (int i = 0; i < n; i++){
ps[i].read();
}
double l=0, r=100000000;
while (dcmp(r-l)>0){
double mid = (l + r) / 2;
if (judge(mid)) l = mid;
else r = mid;
}
printf("%.6lf\n", l);
}
return 0;
}