给你一个凸多边形,问在里面距离凸边形最远的点。
方法就是二分这个距离,然后将对应的半平面沿着法向平移这个距离,然后判断是否交集为空,为空说明这个距离太大了,否则太小了,二分即可。
#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 ", l); } return 0; }