zoj 3272 || hdu 3264 Open-air shopping malls(1Y哦~~哈哈哈哈~)

来源:互联网 发布:js实现黑洞特效 编辑:程序博客网 时间:2024/05/19 05:33

2009 Asia Ningbo Regional Contest 。。。2009GB他们参加的那个区域赛的计算几何题~

给你N个圆,求一个圆,圆心在这个N个圆的其中一个圆心上,使得半径 r 可以覆盖到所有的圆使得所有圆的覆盖面积大于它自身的一半。求这个最小的半径。

分析可知,当正好覆盖到某个圆的一半的时候,这个半径最小。

因为圆最多才20个,所以枚举圆心,对于每个圆心,二分半径,最终确定最小半径即可。对于每个圆心,最小半径肯定是大于离它最近的圆的圆心距,最大的一定是小于离它最远的圆的圆心距+那个圆的半径。

如果有一个圆覆盖的面积比一半小,那么说明这个半径小了,如果都比一半大,说明这个半径大了,有一个正好说明这个半径可取~

刚搜了下,基本都是这个做法。。。

#include <set>#include <map>#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define BUG puts("here!!!")using namespace std;const int MAX = 25;const double inf = 1e30;const double pi = acos(-1.0);struct point { double x,y;};struct circle{point c;double r;double area(){return pi*r*r;};};circle c[MAX];const double eps = 1e-6;bool dy(double x,double y){return x > y + eps;}// x > y bool xy(double x,double y){return x < y - eps;}// x < y bool dyd(double x,double y){ return x > y - eps;}// x >= y bool xyd(double x,double y){return x < y + eps;} // x <= y bool dd(double x,double y) {return fabs( x - y ) < eps;}  // x == ydouble disp2p(point a,point b) //  a b 两点之间的距离 {return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );}bool c2c_sep(point c1,double r1,point c2,double r2){return dy(disp2p(c1,c2), r1 + r2);}double gongxing_area(double r1,double r2,double l) // 两圆半径以及连心线长度 {    double cosaa = (r1*r1 + l*l - r2*r2)/(2*r1*l);      // cos值       double fcosaa = acos(cosaa)*2;      //夹角       double Shu = fcosaa*r1*r1/2;          // 扇形面积       double Ssan = r1*r1*sin(fcosaa)/2;  // 三角形面积       return (Shu - Ssan);                //扇形面积减去三角形面积  }bool c2c_ainb(point a,double r1,point b,double r2){return xy(disp2p(a,b),r2 - r1);//a在b中,如果是包括内切,用xyd }double c2c_inst_area(point a,double r1,point b,double r2){if( c2c_ainb(a,r1,b,r2) )return pi*r1*r1;// a内含于b if( c2c_ainb(b,r2,a,r1) )return pi*r2*r2;// b内含于a double l = disp2p(a,b);// 如果单纯求相交面积,需判断相交,从这儿到下面这段 return gongxing_area(r1,r2,l) + gongxing_area(r2,r1,l);}int compute(point c,double r, int n,circle *cc){int flag = 0;for(int i=0; i<n; i++){if( c2c_sep(c, r, cc[i].c, cc[i].r) )return -1;double inst_area = c2c_inst_area(c, r, cc[i].c, cc[i].r);if( xy(inst_area*2, cc[i].area()) )return -1;if( dd(inst_area*2, cc[i].area()) )flag = 1;}if( flag == 0 ) return 1;return 0;}double circle_r(int x,int n){double minr = inf,maxr = 0;for(int i=0; i<n; i++){if( i == x ) continue;double len = disp2p(c[i].c, c[x].c);if( dy(len + c[i].r, maxr) )maxr = len + c[i].r;if( xy(len, minr) )minr = len;}double begin = minr, end = maxr;while( begin != end ){double mid = (begin + end) / 2.0;int flag = compute(c[x].c, mid, n, c);if( flag == 0 ) return mid;if( flag == 1 )end = mid;elsebegin = mid;}return -1;} double solve(int n){double r = inf;for(int i=0; i<n; i++){double ans = circle_r(i,n);if( xy(ans,r) ) r = ans;}return r;}int main(){int n,ncases;scanf("%d",&ncases);while( ncases-- ){scanf("%d", &n);for(int i=0; i<n; i++)scanf("%lf%lf%lf", &c[i].c.x, &c[i].c.y, &c[i].r);if( n == 1 ){printf("%.4lf\n",sqrt(c[0].r*c[0].r/2));continue;}double ans = solve(n);printf("%.4lf\n",ans);}return 0;}


原创粉丝点击