题目链接:J-Distance to Work
思路分析: 板子题,简单多边形和圆面积交 + 二分
代码如下:
#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;
}