2018牛客網暑期ACM多校訓練第三場 J-Distance to Work
阿新 • • 發佈:2019-02-04
思路分析: 板子題,簡單多邊形和圓面積交 + 二分
程式碼如下:
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const double eps = 1e-8; const double PI = acos(-1.0); inline int dcmp(double x) { if (x<-eps) return -1; return x>eps?1:0; } struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} }; typedef Point Vector; Vector operator +(Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y); } Vector operator -(Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y); } Vector operator *(Vector A,double p) {return Vector(A.x*p,A.y*p); } double Dot(Vector A,Vector B) {return A.x*B.x + A.y*B.y;} double Cross(Vector A, Vector B) {return A.x*B.y-A.y*B.x;} double Length(Vector A) {return sqrt(Dot(A,A)); } double sqr(double x) {return x*x;} double Triangle_cross_Circle(Point A,Point B, Point C, double r){ double a,b,c,x,y; double s = 0.5*Cross(A-C,B-C); a = Length(B-C); b = Length(A-C); c = Length(A-B); if (a <= r && b <= r) return s; else if (a<r && b>=r) { x = (Dot(A-B,C-B) + sqrt(c*c*r*r - sqr(Cross(A-B,C-B))))/c; return asin(s*(c-x)*2.0/c/b/r)*r*r*0.5 + s*x/c; } else if (a >= r && b<r) { y = (Dot(B-A,C-A) + sqrt(c*c*r*r - sqr(Cross(B-A,C-A))))/c; return asin(s*(c-y)*2.0/c/a/r)*r*r*0.5 + s*y/c; } else { if (fabs(2.0*s) >= r*c || Dot(B-A,C-A) <= 0 || Dot(A-B,C-B) <= 0) { if (Dot(A-C,B-C) < 0) { if (Cross(A-C,B-C) < 0) return (-PI - asin(s*2.0/a/b))*r*r*0.5; else return (PI - asin(s*2.0/a/b))*r*r*0.5; } else return asin(s*2.0/a/b)*r*r*0.5; } else { x = (Dot(A-B,C-B) + sqrt(c*c*r*r - sqr(Cross(A-B,C-B))))/c; y = (Dot(B-A,C-A) + sqrt(c*c*r*r - sqr(Cross(B-A,C-A))))/c; return (asin(s*(1-x/c)*2/r/b) + asin(s*(1-y/c)*2/r/a))*r*r*0.5 + s*((y+x)/c-1); } } } const int maxn = 1000; int n,m; Point p[maxn]; double check(int n, Point cir, double r){ double res = 0.0; for (int i=0; i<n; ++i) res += Triangle_cross_Circle(p[i],p[i+1],cir,r); return fabs(res); } int main(){ while (scanf("%d",&n) == 1) { for (int i=0; i<n; ++i) scanf("%lf%lf",&p[i].x,&p[i].y); p[n] = p[0]; double poly_area = 0.0; for (int i=0; i<n; ++i) poly_area += Cross(p[i],p[i+1]); poly_area = fabs(poly_area)*0.5; scanf("%d",&m); while (m--) { Point cir; double a,b; scanf("%lf%lf%lf%lf",&cir.x,&cir.y,&a,&b); a = b-a; double l = 0, r = 1e7; for (int i=0; i<60; ++i) { double mid = (l+r)*0.5; if (check(n,cir,mid)*b > poly_area*a) r = mid; else l = mid; } printf("%.10f\n",l); } } return 0; }