求能放在凸多边形里的最大圆的半径。
我是根据分类刷的 = =。。上面都有做法捏。二分长度,然后用半平面交验证,如果半平面交后的面积为0,那么就是需要的结果了。
注意精度开得稍微大点。我用的N*LOGN的,这个一直不行,因为用这个算法的话,如果半平面交为0,不代表他们缩在一起了,有可能距离过大,交错开了。 T T 。一直没有好的解决方案。昨晚还开了一个求面积,求半平面交反向后的面积,不过还是不可以,即使他们两个面积都为0,还是不能确保他们缩的最小 = =。。后来把它改成判长度了,如果交错开,那么len = -1,这样的话,如果len = -1,说明交的区域无穷大 或者不能构成一个凸多边形,那么继续二分。如果len == 1,说明最终就交到一个点。
#include <cmath> #include <cstdio> #include <cstdlib> #include <iostream> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <stack> #include <climits> using namespace std; const int MAX = 110; const double eps = 1e-8; const double inf = 1e20; struct point {double x,y;}; struct line{point a,b; double ang;}; point p[MAX],s[MAX]; line ln[MAX],deq[MAX]; bool dy(double x,double y) { return x > y + eps;} // x > y bool xy(double x,double y) { return x < y - eps;} // x < y bool dyd(double x,double y) { return x > y - eps;} // x >= y bool xyd(double x,double y) { return x < y + eps;} // x <= y bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y bool parallel(line u,line v) { return dd( (u.a.x - u.b.x)*(v.a.y - v.b.y) - (v.a.x - v.b.x)*(u.a.y - u.b.y) , 0.0 ); } double disp2p(point a,point b) // a b 两点之间的距离 { return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) ); } double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向 { return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y); } point l2l_inst_p(line l1,line l2) { point ans = l1.a; double t = ((l1.a.x - l2.a.x)*(l2.a.y - l2.b.y) - (l1.a.y - l2.a.y)*(l2.a.x - l2.b.x))/ ((l1.a.x - l1.b.x)*(l2.a.y - l2.b.y) - (l1.a.y - l1.b.y)*(l2.a.x - l2.b.x)); ans.x += (l1.b.x - l1.a.x)*t; ans.y += (l1.b.y - l1.a.y)*t; return ans; } void makeline_hp(double x1,double y1,double x2,double y2,line &l) { l.a.x = x1; l.a.y = y1; l.b.x = x2; l.b.y = y2; l.ang = atan2(y1 - y2,x1 - x2); } void makeline_hp(point a,point b,line &l) { l.a = a; l.b = b; l.ang = atan2(a.y - b.y,a.x - b.x); } bool equal_ang(line a,line b) // 第一次unique的比较函数 { return dd(a.ang,b.ang); } bool cmphp(line a,line b) // 排序的比较函数 { if( dd(a.ang,b.ang) ) return xy(crossProduct(b.a,b.b,a.a),0.0); return xy(a.ang,b.ang); } bool equal_p(point a,point b)//第二次unique的比较函数 { return dd(a.x,b.x) && dd(a.y,b.y); } void inst_hp_nlogn(line *ln,int n,point *s,int &len) { len = 0; sort(ln,ln+n,cmphp); n = unique(ln,ln+n,equal_ang) - ln; int bot = 0,top = 1; deq[0] = ln[0]; deq[1] = ln[1]; for(int i=2; i<n; i++) { if( parallel(deq[top],deq[top-1]) || parallel(deq[bot],deq[bot+1]) ) { len = -1; return ; } while( bot < top && dy(crossProduct(ln[i].a,ln[i].b, l2l_inst_p(deq[top],deq[top-1])),0.0) ) top--; while( bot < top && dy(crossProduct(ln[i].a,ln[i].b, l2l_inst_p(deq[bot],deq[bot+1])),0.0) ) bot++; deq[++top] = ln[i]; } while( bot < top && dy(crossProduct(deq[bot].a,deq[bot].b, l2l_inst_p(deq[top],deq[top-1])),0.0) ) top--; while( bot < top && dy(crossProduct(deq[top].a,deq[top].b, l2l_inst_p(deq[bot],deq[bot+1])),0.0) ) bot++; if( top <= bot + 1 ){ len = -1; return ;} for(int i=bot; i<top; i++) s[len++] = l2l_inst_p(deq[i],deq[i+1]); if( bot < top + 1 ) s[len++] = l2l_inst_p(deq[bot],deq[top]); len = unique(s,s+len,equal_p) - s; return ; } void changepoint(point a,point b,point &c,point &d,double h) { double len = disp2p(a,b); double dx = h / len * ( a.y - b.y ); double dy = h / len * (-a.x + b.x ); c.x = a.x + dx; c.y = a.y + dy; d.x = b.x + dx; d.y = b.y + dy; } double dis_ch(point p[],int n) { double d = -inf; for(int i=0; i<n; i++) for(int k=i+1; k<n; k++) { double len = disp2p(p[i],p[k]); if( dy(len,d) ) d = len; } return d; } int main() { int n; double mid; while( ~scanf("%d",&n) && n ) { for(int i=0; i<n; i++) scanf("%lf%lf",&p[i].x,&p[i].y); p[n] = p[0]; double d = dis_ch(p,n); double b = 0.0,e = d; while( !dd(b,e) ) { mid = (b+e)/2; for(int i=0; i<n; i++) { point c,d; changepoint(p[i],p[i+1],c,d,mid); makeline_hp(c,d,ln[i]); } int len; inst_hp_nlogn(ln,n,s,len); if( len == 1 ) break; if( len == -1 ) e = mid; else b = mid; } printf("%.6lf\n",mid); } return 0; }