题意:N(1<=N<=20) 个圆,现取其中一个圆的圆心为圆心作一个大圆,使得这个大圆与其他任意一个圆 c 的面积交 >= c 的面积的一半,求大圆的最小半径。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3264
——>>枚举圆心,二分半径。。
#include <cstdio> #include <cmath> #include <algorithm> using std::min; const double EPS = 1e-8; const double PI = acos(-1.0); const int MAXN = 20 + 10; int N; double harea[MAXN]; int Dcmp(double x) { if (fabs(x) < EPS) return 0; return x > 0 ? 1 : -1; } struct POINT { double x; double y; POINT(double x = 0.0, double y = 0.0) : x(x), y(y) {} }; typedef POINT VECTOR; struct CIRCLE { POINT c; double r; CIRCLE() {} CIRCLE(POINT c, double r) : c(c), r(r) {} } mall[MAXN]; double Length(POINT A, POINT B) { return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)); } // 两圆面积交 double AreaCircleCircle(CIRCLE c1, CIRCLE c2) { double ret = 0.0; double d = Length(c1.c, c2.c); if (Dcmp(d - c1.r - c2.r) < 0 && Dcmp(d - fabs(c1.r - c2.r)) > 0) { double a1 = acos((c1.r * c1.r + d * d - c2.r * c2.r) / 2 / c1.r / d); double a2 = acos((c2.r * c2.r + d * d - c1.r * c1.r) / 2 / c2.r / d); ret = (a1 - sin(2 * a1) / 2) * c1.r * c1.r + (a2 - sin(2 * a2) / 2) * c2.r * c2.r; } else if (Dcmp(d - fabs(c1.r - c2.r)) <= 0) { if (Dcmp(c1.r - c2.r) < 0) { ret = PI * c1.r * c1.r; } else { ret = PI * c2.r * c2.r; } } return ret; } void Read() { scanf("%d", &N); for (int i = 0; i < N; ++i) { scanf("%lf%lf%lf", &mall[i].c.x, &mall[i].c.y, &mall[i].r); harea[i] = PI * mall[i].r * mall[i].r / 2; } } bool IsOk(const POINT& center, const double& r) { for (int i = 0; i < N; ++i) { if (Dcmp(AreaCircleCircle(CIRCLE(center, r), mall[i]) - harea[i]) < 0) { return false; } } return true; } void Solve() { double ret = 34000.0; for (int i = 0; i < N; ++i) { double L = 0.0; double R = 34000.0; while (Dcmp(L - R) < 0) { double M = (L + R) / 2; IsOk(mall[i].c, M) ? R = M : L = M; } ret = min(ret, L); } printf("%.4f\n", ret); } int main() { int T; scanf("%d", &T); while (T--) { Read(); Solve(); } return 0; }