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

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

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

#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;

}

 

你可能感兴趣的:(ant)