分相离,内含,想交三种情况讨论一下。
主要是精度和数据范围的问题,首先数据用long double,能用整型判断就不要用浮点型。
题目中所给的坐标,半径是整型的,出现卡浮点判断的情况还是比较少的。
最后算三角型面积的时候不要用海伦公式,有四个连乘很容易爆数据范围损失精度,即使拆开两两乘也要考虑符号
(取对数也是比较好的办法)。(不知道sqrt和cos,sin的精度如何比较
#include<bits/stdc++.h> using namespace std; typedef long double ld; typedef long long ll; ld x[2],y[2],r[2]; inline ld sqr(ld x){ return x*x; } inline ll sqrl(ll x) { return x*x; } inline ld fcos(ld a, ld b, ld c) { return acosl((a*a+b*b-c*c)/(2*a*b)); } inline ld cut(ld ang, ld r) { ld s1 = ang*r*r; ld s2 = sinl(ang)*cosl(ang)*r*r; return s1 - s2; } const ld pi = acosl(-1); double solve() { if(r[0] > r[1]){ swap(r[0],r[1]); swap(x[0],x[1]); swap(y[0],y[1]); } ll dx = x[0]-x[1], dy = y[0]-y[1]; ll ds = sqrl(dx)+sqrl(dy); if(ds >= sqrl(r[0]+r[1])) return 0; ld d = sqrtl(ds); if(d+r[0] <= r[1]) return sqr(r[0])*pi; ld ang[2]; ang[0] = fcos(d,r[0],r[1]); ang[1] = fcos(d,r[1],r[0]); /* WA 28 ld area = ang[1]*sqr(r[1]) + ang[0]*sqr(r[0]); ld s = (d+r[0]+r[1])/2; area -= sqrtl(s*(s-d)*(s-r[0])*(s-r[1]))*2; // O(n^4) 拆分会有符号问题 对数也许可行 return area; */ return cut(ang[0],r[0]) + cut(ang[1],r[1]); } //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif cin>>x[0]>>y[0]>>r[0]>>x[1]>>y[1]>>r[1]; printf("%.10f\n", solve()); return 0; }
codeforces 600D Area of Two Circles' Intersection
时间: 2024-10-12 07:15:35