题目链接 :HDU 3264 Open-air shopping malls
题意:给出n个圆。要求一个在n个圆的圆心建一个大圆,使大圆与每一个小圆的交面积大于等于该小圆的面积的一般。求最小的大圆半径。
思路:二分大圆半径,枚举每个小圆与大圆的交面积。
注意精度问题。
AC代码:
#include <stdio.h> #include <math.h> #include <algorithm> const double eps=1e-6; const double PI=acos(-1.0); using namespace std; struct point { double x,y; double r; }; struct point p[30]; double dist(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double Area_of_overlap(point c1, double r1, point c2, double r2) { double d = dist(c1,c2); if(r1 + r2 < d + eps) return 0; if(d < fabs(r1 - r2) + eps) { double r = min(r1,r2); return PI*r*r; } double x = (d*d + r1*r1 - r2*r2)/(2*d); double t1 = acos(x / r1); double t2 = acos((d - x)/r2); return r1*r1*t1 + r2*r2*t2 - d*r1*sin(t1); } bool check(point p[],int n,point s,double r,int pos) { int i; for(i=0; i<n; i++) { double area_s,area_p; area_s=p[i].r*p[i].r*PI;//p[i]面积 area_p=Area_of_overlap(s,r,p[i],p[i].r); if(area_s/2.0-area_p>eps)//没半圆 return true; } return false; } int main() { int t,i,n; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0; i<n; i++) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r); double l,r,mid; double minn=20100.0; for(i=0; i<n; i++) { l=0,r=20100.0; while((r-l)>eps) { mid=(l+r)/2.0; if(check(p,n,p[i],mid,i)) l=mid+eps; else r=mid-eps; } minn=min(minn,l); } printf("%.4lf\n",minn); } return 0; } /* 3 5 0 0 1 2 0 1 0 2 1 -2 0 1 0 -2 1 2 0 0 1 2 0 1 1 0 0 1 */
时间: 2024-10-27 18:06:07