LA3890 Most Distant Point from the Sea
阿新 • • 發佈:2018-12-23
題意
分析
可以二分答案,檢驗就用半平面交,如果平面非空則合法。
時間複雜度\(O(T n \log^2 n)\)
程式碼
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<set> #include<map> #include<queue> #include<stack> #include<algorithm> #include<bitset> #include<cassert> #include<ctime> #include<cstring> #define rg register #define il inline #define co const template<class T>il T read() { rg T data=0; rg int w=1; rg char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') w=-1; ch=getchar(); } while(isdigit(ch)) { data=data*10+ch-'0'; ch=getchar(); } return data*w; } template<class T>T read(T&x) { return x=read<T>(); } using namespace std; typedef long long ll; struct Point { double x,y; Point(double x=0,double y=0) :x(x),y(y){} }; typedef Point Vector; Vector operator+(co Vector&A,co Vector&B) { return Vector(A.x+B.x,A.y+B.y); } Vector operator-(co Vector&A,co Vector&B) { return Vector(A.x-B.x,A.y-B.y); } Vector operator*(co Vector&A,double p) { return Vector(A.x*p,A.y*p); } Vector operator/(co Vector&A,double p) { return Vector(A.x/p,A.y/p); } double Dot(co Vector&A,co Vector&B) { return A.x*B.x+A.y*B.y; } double Cross(co Vector&A,co Vector&B) { return A.x*B.y-A.y*B.x; } double Length(co Vector&A) { return sqrt(Dot(A,A)); } Vector Normal(co Vector&A) { double L=Length(A); return Vector(-A.y/L,A.x/L); } double PolygonArea(vector<Point> p) { int n=p.size(); double area=0; for(int i=1;i<n-1;++i) area+=Cross(p[i]-p[0],p[i+1]-p[0]); return area/2; } struct Line { Point P; Vector v; Line(Point P=0,Vector v=0) :P(P),v(v){} double angle()co { return atan2(v.y,v.x); } bool operator<(co Line&rhs)co { return angle()<rhs.angle(); } }; bool OnLeft(co Line&L,co Point&p) { return Cross(L.v,p-L.P)>0; } Point LineLineIntersection(co Line&a,co Line&b) { Vector u=a.P-b.P; double t=Cross(b.v,u)/Cross(a.v,b.v); return a.P+a.v*t; } co double INF=1e8; co double eps=1e-6; vector<Point>HalfplaneIntersection(vector<Line>L) { int n=L.size(); sort(L.begin(),L.end()); int first,last; vector<Point>p(n); vector<Line>q(n); vector<Point>ans; q[first=last=0]=L[0]; for(int i=1;i<n;++i) { while(first<last&&!OnLeft(L[i],p[last-1])) --last; while(first<last&&!OnLeft(L[i],p[first])) ++first; q[++last]=L[i]; if(fabs(Cross(q[last].v,q[last-1].v))<eps) { --last; if(OnLeft(q[last],L[i].P)) q[last]=L[i]; } if(first<last) p[last-1]=LineLineIntersection(q[last-1],q[last]); } while(first<last&&!OnLeft(q[first],p[last-1])) --last; if(last-first<=1) return ans; p[last]=LineLineIntersection(q[last],q[first]); for(int i=first;i<=last;++i) ans.push_back(p[i]); return ans; } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); int n; while(read(n)) { vector<Vector>p,v,normal; for(int i=0;i<n;++i) p.push_back(Point(read<int>(),read<int>())); if(PolygonArea(p)<0) reverse(p.begin(),p.end()); for(int i=0;i<n;++i) { v.push_back(p[(i+1)%n]-p[i]); normal.push_back(Normal(v[i])); } double left=0,right=2e4; while(right-left>eps) { vector<Line>L; double mid=(left+right)/2; for(int i=0;i<n;++i) L.push_back(Line(p[i]+normal[i]*mid,v[i])); vector<Point>poly=HalfplaneIntersection(L); if(poly.empty()) right=mid; else left=mid; } printf("%.6lf\n",left); } return 0; }