Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <iomanip>
- #include <cmath>
- #include <functional>
- #include <cassert>
- using namespace std;
- typedef int64_t Int;
- typedef long double Real;
- const Real PI = std::acos(-1.0L);
- Real solve(Int x1, Int y1, Int r1, Int x2, Int y2, Int r2) {
- assert(r1 >= r2);
- Int dist2 = (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
- if (dist2 >= (r1+r2)*(r1+r2)) { // пересечений нет
- return 0;
- }
- // r1 >= dist + r2 - площадь меньшего круга
- if ((r1-r2)*(r1-r2) >= dist2) {
- return PI * r2 * r2;
- }
- Real dist = std::sqrt(Real(dist2));
- // r2^2 = r1^2 + d^2 - 2 * b * d * cos(alpha)
- // r2^2 - r1^2 - d^2 = - 2 * r1 * d * cos(alpha)
- // acos((-r2^2 + r1^2 + d^2) / r1 / d / 2)
- std::function<Real(Int, Int, Int)> angle = [](Int a, Int b, Int c) {
- // a^2 = b^2+d^2-2*b*d*cos(alpha)
- Real cos_alpha = Real(b*b+c*c-a*a) / b / c / 2;
- cos_alpha = std::min(cos_alpha, 1.0L);
- cos_alpha = std::max(cos_alpha, -1.0L);
- return std::acos(cos_alpha);
- };
- if (r1 * r1 >= dist2 + r2 * r2) { // угол тупой
- //std::cout << "two" << std::endl;
- Real alpha = angle(r1, r2, dist);
- Real beta = angle(r2, r1, dist);
- //assert(2*alpha >= PI);
- Real s_triangle = dist * r2 * std::sin(alpha) / 2;
- Real S1 = r2 * r2 * alpha;
- Real S2 = r1 * r1 * beta - 2 * s_triangle;
- //cout << "S1 = " << S1 << ", S2 = " << S2 << endl;
- return S1 + S2;
- } else {
- Real alpha = angle(r2, r1, dist);
- Real beta = angle(r1, r2, dist);
- // sin(a) = c / r1
- // c = 2 * r1 * sin(a)
- return alpha * r1 * r1 + beta * r2 * r2 - dist * r1 * std::sin(alpha);
- }
- }
- int main() {
- //freopen("input.txt", "rt", stdin);
- Int x1, y1, r1, x2, y2, r2;
- cin >> x1 >> y1 >> r1;
- cin >> x2 >> y2 >> r2;
- if (r1 < r2) {
- swap(x1, x2);
- swap(y1, y2);
- swap(r1, r2);
- }
- cout << fixed << setprecision(8) << solve(x1, y1, r1, x2, y2, r2) << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement