【计算几何】【二分】【随机增量法】hdu6167 Missile Interception
n个半径为R的圆是否有公共部分,等价于询问是否存在一个半径小于R的圆,能覆盖所有n个圆的圆心。
对这n个点求最小圆覆盖即可。从网上扒了个随机增量法的代码。
这样算上二分,复杂度就是nlogn了。
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const double eps=0.000000001; int n; double V,x[103],y[103],dx[103],dy[103],v[103],cx[103],cy[103]; struct node { double x,y; }; node p[1000001]; double r; node O; double dist(node a,node b) { return sqrt( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) ); } void calc(double a,double b,double c,double d,double e,double f) { O.y=(c*d-f*a)/(b*d-e*a); O.x=(c*e-f*b)/(a*e-b*d); } double get() { for (int i=1;i<=n;++i) { p[i].x=cx[i]; p[i].y=cy[i]; } O=p[1];r=0; for(int i=2;i<=n;++i) if(dist(O,p[i])>r+1e-6) { O=p[i];r=0; for (int j=1;j<=i-1;++j) if (dist(O,p[j])>r+1e-6) { O.x=(p[i].x+p[j].x)/2; O.y=(p[i].y+p[j].y)/2; r=dist(O,p[j]); for (int k=1;k<=j-1;++k) if (dist(O,p[k])>r+1e-6) { calc(p[j].x-p[i].x,p[j].y-p[i].y,(p[j].x*p[j].x+p[j].y*p[j].y-p[i].x*p[i].x-p[i].y*p[i].y)/2, p[k].x-p[i].x,p[k].y-p[i].y,(p[k].x*p[k].x+p[k].y*p[k].y-p[i].x*p[i].x-p[i].y*p[i].y)/2); r=dist(O,p[k]); } } } return r; } bool check(double t) { for(int i=1;i<=n;++i) { cx[i]=x[i]+dx[i]*t*v[i]; cy[i]=y[i]+dy[i]*t*v[i]; } return get()<t*V+eps; } int main() { while(scanf("%d%lf",&n,&V)!=EOF) { for(int i=1;i<=n;++i) { scanf("%lf%lf%lf%lf%lf",&x[i],&y[i],&dx[i],&dy[i],&v[i]); double l=sqrt(dx[i]*dx[i]+dy[i]*dy[i]); dx[i]/=l; dy[i]/=l; } double l=0,r=9999999; while(l<r-eps) { double mid=(l+r)*0.5; if(check(mid)) r=mid; else l=mid; } printf("%.4lf\n",r); } return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/