题目来源:
http://acm.uestc.edu.cn/#/problem/show/814
题意:是给你一堆凸包上的点,这些点会形成一个凸多边形,有两个god站在这个多边形上,他们可以释放一个半径为r的魔法火圈,我们要求的就是两个god放出来的火圈完全覆盖这个多边形时的最小半径。
我的方法是二分半径,然后判断能否覆盖这个多边形是枚举每一条线段,判断每一条线段是否都能被一个圆,或者两个圆完全覆盖,如果能那么这个多边形就能完全被覆盖,只有有一条边不满足覆盖, 则这个多边形不能完全被覆盖。
其中判断一条跨两个圆的线段能否被两个圆完全覆盖时,用的二分,去找线段上是否存在一个点,同时在两个圆内,如果存在则这条线段能被两个圆完全覆盖。
代码如下:
#include <iostream> #include <algorithm> #include <stdlib.h> #include <stdio.h> #include <stack> #include <string> #include <string.h> #include<cstring> #include <algorithm> #include <stdlib.h> #include <vector> #include <set> #include <math.h> #include <cmath> #include <map> #include <queue> using namespace std ; typedef long long LL ; const double EPS = 1e-10; const int Max_N = 25; double add(double x, double y){ if (fabs(x+y) < EPS*( fabs(x)+fabs(y)) ) return 0; return x+y; } struct Point { double x,y; Point(){} Point(double x, double y):x(x),y(y){} double dist(Point p){ return sqrt( (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y) ); } }; Point p[Max_N]; Point mag[3]; int n; // 跨圆的线段, 二分寻找是否存在一个点, 同时在2个圆内 int judge(Point l,Point r, Point ml, Point mr, double ra){ Point mid; while( fabs(l.dist(r)) > EPS ){ mid.x= (l.x + r.x) * 0.5; mid.y= (l.y + r.y) * 0.5; double d1=(ml.dist(mid) - ra); double d2=(mr.dist(mid) - ra); if(d1<=0 && d2<=0) return 1; if(d1 <= 0) l=mid; else r=mid; } return 0; } int judge1(double r){ // 枚举所有线段,看每条线段是否都能被覆盖 int i,j; for(i=0; i<n-1; i++){ for(j=i+1;j<n; j++){ double r1,r2,r3,r4; r1=(p[i].dist(mag[1]) - r); r2=(p[j].dist(mag[1]) - r); r3=(p[i].dist(mag[2]) - r); r4=(p[j].dist(mag[2]) - r); if( (r1<= 0 && r2<= 0) || (r3<=0 && r4<=0) ) continue; if( r1 <=0 && r4<=0 ){ if(judge(p[i] ,p[j],mag[1],mag[2], r)) // judge判断一条跨线是否被覆盖 continue; } if(r2<=0 && r3<=0){ if(judge( p[i],p[j],mag[2],mag[1],r )) continue; } return 0; } } return 1; } int main(){ while(~scanf("%d" ,&n)){ for(int i=0; i<n; i++) scanf("%lf%lf",&p[i].x, &p[i].y ); for(int i=1; i<=2; i++) scanf("%lf%lf",&mag[i].x, &mag[i].y); double ll=0.0, lr=4000.0; // lr不能开太小, 可以开大些 double md; while(ll+ EPS <lr ){ //二分半径 md=(ll + lr) * 0.5; if(judge1(md)) lr=md; else ll=md; } printf("%.3lf\n",md); } }