标签:style blog http io ar os sp for on
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3264
题意:
给定n个圆的圆心和半径,求一个圆心为这些圆中任意一个,与所有圆相交的面积超过其面积一半的圆的最小半径。
分析:
枚举圆心,然后二分得到最小的半径,直接套求圆交的模板。
代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const double eps = 1e-8; const double pi = acos(-1.0); int n; struct point { double x,y,r; }cir[25]; double S(point a) { return pi*a.r*a.r; } double dis(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double calu(point a,point b) { point tmpa=a,tmpb=b; if(tmpa.r<tmpb.r) swap(tmpa,tmpb); double area = 0; double dd = dis(tmpa,tmpb); if(dd>tmpa.r-tmpb.r&&dd<tmpa.r+tmpb.r){ double cos1 = (tmpa.r*tmpa.r+dd*dd-tmpb.r*tmpb.r)/(2*tmpa.r*dd); double cos2 = (tmpb.r*tmpb.r+dd*dd-tmpa.r*tmpa.r)/(2*tmpb.r*dd); double th1 = 2*acos(cos1); double th2 = 2*acos(cos2); double s1 = 0.5*tmpa.r*tmpa.r*sin(th1); double s2 = 0.5*tmpb.r*tmpb.r*sin(th2); double s3 = (th1/2)*tmpa.r*tmpa.r; double s4 = (th2/2)*tmpb.r*tmpb.r; area = s3+s4-s1-s2; } else if(dd<=tmpa.r-tmpb.r) area = S(tmpb); return area; } bool check(point a) { for(int i=0;i<n;i++){ if(calu(a,cir[i])*2<pi*cir[i].r*cir[i].r) return false; } return true; } double bin_search(double l,double r,point tmp) { double mid; while(r-l>=eps){ mid=(l+r)/2.0; tmp.r=mid; if(check(tmp)) r=mid; else l=mid+eps; } return mid; } int main() { int t; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lf%lf%lf",&cir[i].x,&cir[i].y,&cir[i].r); point ans; double r=1000000; for(int i=0;i<n;i++){ ans.x=cir[i].x,ans.y=cir[i].y; r=min(r,bin_search(0,30000,ans)); } printf("%.4lf\n",r); } return 0; }
HDU3264 Open-air shopping malls (圆交+二分)
标签:style blog http io ar os sp for on
原文地址:http://blog.csdn.net/bigbigship/article/details/41865911