HDU 3264 Open-air shopping malls (计算几何-圆相交面积)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3264


题意:给你n个圆,坐标和半径,然后要在这n个圆的圆心画一个大圆,大圆与这n个圆相交的面积必须大于等于每个圆面积的一半,问你建在那个圆心半径最小,为多少。

题解:枚举这n个圆,求每个圆的最小半径,通过二分半径来求,然后取这n个的最小值即可,注意点精度就OK了。


AC代码:

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <string>

#include <cstdlib>

#include <cmath>

#include <vector>

#include <list>

#include <deque>

#include <queue>

#include <iterator>

#include <stack>

#include <map>

#include <set>

#include <algorithm>

#include <cctype>

using namespace std;



#define si1(a) scanf("%d",&a)

#define si2(a,b) scanf("%d%d",&a,&b)

#define sd1(a) scanf("%lf",&a)

#define sd2(a,b) scanf("%lf%lf",&a,&b)

#define ss1(s)  scanf("%s",s)

#define pi1(a)    printf("%d\n",a)

#define pi2(a,b)  printf("%d %d\n",a,b)

#define mset(a,b)   memset(a,b,sizeof(a))

#define forb(i,a,b)   for(int i=a;i<b;i++)

#define ford(i,a,b)   for(int i=a;i<=b;i++)



typedef long long LL;

const int N=33;

const int INF=0x3f3f3f3f;

const double PI=acos(-1.0);

const double eps=1e-8;



int n;



struct xkn

{

    double x,y,r;

    double area;

}p[22],h;



double dis(xkn a,xkn b)

{

    return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );

}



double fuck(xkn a,xkn b)  //求两圆的相交面积函数。

{

    double d=dis(a,b);

    if(d>=a.r+b.r) return 0;

    double r=(a.r>b.r?b.r:a.r);

    if( d<=fabs(a.r-b.r) ) return PI*r*r;

    double A1=acos( (a.r*a.r+d*d-b.r*b.r)/2/a.r/d );

    double A2=acos( (b.r*b.r+d*d-a.r*a.r)/2/b.r/d );

    double res=A1*a.r*a.r + A2*b.r*b.r;

    res-=sin(A1)*a.r*d;

    return res;

}



bool xiaohao(xkn h)

{

    for(int i=0;i<n;i++)

    {

        double jiao=fuck(p[i],h);

        if(jiao<p[i].area/2)

            return false;

    }

    return true;

}



int main()

{

//    freopen("input.txt","r",stdin);

    int T;

    si1(T);

    while(T--)

    {

        si1(n);

        for(int i=0;i<n;i++)

        {

            sd2(p[i].x,p[i].y);

            sd1(p[i].r);

            p[i].area=PI*p[i].r*p[i].r;

        }

        double Min=55555;

        for(int i=0;i<n;i++)

        {

            double l=0,r=22222,m;

            while((r-l)>eps)

            {

                m=(l+r)/2;

                h=p[i]; h.r=m;

                if(xiaohao(h))

                    r=m;

                else

                    l=m;

            }

            if(Min>m)   Min=m;

        }

        printf("%.4f\n",Min);

    }

    return 0;

}

//9253993	2013-09-30 19:54:36	Accepted	3264	0MS	320K	2260 B	G++	XH_Reventon


 

 

你可能感兴趣的:(open)