/* 模拟退火法: 找到一些随机点,从这些点出发,随机的方向坐标向外搜索; 最后找到这些随机点的最大值; 坑://if(xx>-eps&&xx<x+eps&&yy>-eps&&yy<eps+y) {不知道为什么这个判断方式错误?????? */ #include<iostream> #include<cstdio> #include<math.h> #include<algorithm> #define pi acos(-1.0) #define N 1100 #define inf 1000000000000 #define eps 1e-8 using namespace std; double x,y; int n; struct node { double u,v,dis; }f[N],endd,ff[N]; double diss(double x,double y,int i) { return sqrt((x-f[i].u)*(x-f[i].u)+(y-f[i].v)*(y-f[i].v)); } double Mindis(double x,double y) { double minn=1.0*inf,ss; int i; for(i=1;i<=n;i++) { ss=diss(x,y,i); if(minn>ss) minn=ss; } return minn; } void compute() { int i,j; double xx,yy; for(i=1;i<=20;i++) {//先随机出来一些点 ff[i].u=(rand()%1000+1)/1000.0*x; ff[i].v=(rand()%1000+1)/1000.0*y; ff[i].dis=Mindis(ff[i].u,ff[i].v); } double T=sqrt(1.0*x*x+1.0*y*y); double rate=0.9; while(T>eps) { for(i=1;i<=20;i++)//对于这些点分别向外搜 for(j=1;j<=30;j++) {//随机30个半径来搜索,更新,得到每个点可以到达的最远距离 double ran=(rand()%1000+1)/1000.0*pi*10; xx=ff[i].u+cos(ran)*T; yy=ff[i].v+sin(ran)*T; //if(xx>-eps&&xx<x+eps&&yy>-eps&&yy<eps+y) {不知道为什么这个判断方式错误?????? if(xx<0.0||xx>x||yy<0.0||yy>y)continue; double di=Mindis(xx,yy); if(ff[i].dis<di) { ff[i].dis=di; ff[i].u=xx; ff[i].v=yy; } } T*=rate;//退火率 } for(i=1;i<=20;i++)//找到最大的一个 if(endd.dis<ff[i].dis) endd=ff[i]; return ; } int main() { // printf("%d ",(rand()%1000+1)/1000.0*2*pi); int m,i,j,k,t; scanf("%d",&t); while(t--) { scanf("%lf%lf%d",&x,&y,&n); for(i=1;i<=n;i++) scanf("%lf%lf",&f[i].u,&f[i].v); endd.dis=-1; compute(); printf("The safest point is (%.1f, %.1f). ",endd.u,endd.v); } return 0; }