1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| #include<algorithm> #include<cstdio> #include<cmath>
using namespace std;
const double eps = 1e-8; const double PI = acos(-1); const double INF = 1e16; inline int sgn(double x){ if(fabs(x) < eps) return 0; else if(x > 0) return 1; else return -1; } inline int cmp(double x, double y){ if(fabs(x-y) < eps) return 0; else if(x > y) return 1; else return -1; }
struct Vector{ double x, y; Vector(double x = 0, double y = 0):x(x), y(y){} void read(){ scanf("%lf%lf", &x, &y); } }; typedef Vector Point; 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 k){ return Vector{A.x * k, A.y * k}; } double operator * (Vector A, Vector B){ return A.x * B.x + A.y * B.y; } double Length(Vector A){ return sqrt(A * A); } double Angle(Vector A){ return atan2(A.y, A.x); } struct Line{ Point p; Vector v; }; struct Circle{ Point p; double r; Point getPoint(double alpha){ return Point(p.x + cos(alpha) * r, p.y + sin(alpha) * r); } }; void getTangents(Circle C1, Circle C2, Point c1[], Point c2[], int &resn){ resn = 0; if(cmp(C1.r, C2.r) < 0) swap(C1, C2), swap(c1, c2); double d = Length(C1.p - C2.p); if(sgn(d) == 0 && cmp(C1.r, C2.r) == 0){ resn = -1; return; } if(cmp(C1.r - C2.r, d) > 0) return; double base = Angle(C2.p - C1.p); if(cmp(C1.r - C2.r, d) == 0){ c1[++resn] = C1.getPoint(base), c2[resn] = C2.getPoint(base); return; } double ang = acos((C1.r - C2.r) / d); c1[++resn] = C1.getPoint(base - ang), c2[resn] = C2.getPoint(base - ang); c1[++resn] = C1.getPoint(base + ang), c2[resn] = C2.getPoint(base + ang);
}
const int N = 1005;
int n; Circle c[N]; double alpha, H[N], R[N], mxR, mnL = 1e9; pair<Point, Point> seg[N]; int sid;
double f(double x){ double mx = 0, res = 0; for(int i = 1; i <= sid; i++){ if(cmp(seg[i].first.x, x) <= 0 && cmp(seg[i].second.x, x) >= 0){ Point p = seg[i].first + (seg[i].second - seg[i].first) * ((x - seg[i].first.x) / (seg[i].second.x - seg[i].first.x)); mx = max(mx, p.y); } } for(int i = 1; i <= n; i++) if(cmp(c[i].r, fabs(x - c[i].p.x)) > 0) mx = max(mx, sqrt(c[i].r * c[i].r - fabs(x - c[i].p.x) * fabs(x - c[i].p.x))); res += mx; return res; } double simpson(double l, double r){ double mid = (l + r) / 2; return (f(l) + 4 * f(mid) + f(r)) * (r - l) / 6; } double solve(double l, double r, double _eps, double I){ double mid = (l + r) / 2; double Il = simpson(l, mid), Ir = simpson(mid, r); if(fabs(Il + Ir - I) <= 15 * _eps) return Il + Ir + (Il + Ir - I) / 15; return solve(l, mid, _eps / 2, Il) + solve(mid, r, _eps / 2, Ir); }
int main(){ scanf("%d%lf", &n, &alpha); double Tan = 1 / tan(alpha); for(int i = 1; i <= n + 1; i++){ scanf("%lf", &H[i]); H[i] += H[i-1]; } for(int i = 1; i <= n + 1; i++){ if(i <= n) scanf("%lf", &R[i]); c[i].p = Point(H[i] * Tan, 0); c[i].r = R[i]; mnL = min(mnL, c[i].p.x - c[i].r); mxR = max(mxR, c[i].p.x + c[i].r); if(i > 1){ Point p1[10], p2[10]; int pid; getTangents(c[i-1], c[i], p1, p2, pid); for(int j = 1; j <= pid; j++){ if(sgn(p1[j].y) <= 0) continue; if(p1[j].x > p2[j].x) swap(p1[j], p2[j]); seg[++sid] = make_pair(p1[j], p2[j]); } } } printf("%.2f\n", 2 * solve(mnL, mxR, 1e-6, simpson(mnL, mxR))); return 0; }
|