/*
模拟退火法:
找到一些随机点,从这些点出发,随机的方向坐标向外搜索;
最后找到这些随机点的最大值;
坑://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\n",(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).\n",endd.u,endd.v);
}
return 0;
}
poj 1379 模拟退火法
最新推荐文章于 2020-02-29 11:09:44 发布