题目描述:
给出一块平面,给出N个点,求平面内的点距离这些点最小距离最大是多少
题目分析:
本题为模拟退火的裸题。
模拟退火详解
我们枚举角度,随机点,温度为半径,随机30组点进行求解
题目链接:
Ac 代码:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cmath>
#define PI std::acos(-1.0)
const int Num=30;
const int maxm=1010;
const double eps=1e-3;
const double r=0.8;
const double inf=1e9+7;
struct node{
double x,y;
}a[maxm],b[maxm];
double dis[maxm];
inline double distance(double x1,double y1,double x2,double y2)
{
return std::sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
inline void work()
{
int n,X,Y;
scanf("%d%d%d",&X,&Y,&n);
for(int i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=1;i<=Num;i++)
{
dis[i]=inf;
b[i].x=(double)(rand()%1000+1)/1000.0*X;
b[i].y=(double)(rand()%1000+1)/1000.0*Y;//随机点值
for(int j=1;j<=n;j++)
dis[i]=std::min(dis[i],distance(b[i].x,b[i].y,a[j].x,a[j].y));
}
double T=(double)std::max(X,Y)/(double)std::sqrt(1.0*n);//初始温度
while(T>eps)
{
for(int i=1;i<=Num;i++)
{
double xx=b[i].x,yy=b[i].y;
for(int j=1;j<=Num;j++)
{
double angle=(double)(rand()%1000+1)/1000.0*2.0*PI;//枚举角度
double bx=T*std::cos(angle);
double by=T*std::sin(angle);
double newx=xx+bx,newy=yy+by;
if(newx>X||newy>Y||newx<eps||newy<eps) continue;
double nowdis=inf;
for(int k=1;k<=n;k++) nowdis=std::min(nowdis,(double)distance(newx,newy,a[k].x,a[k].y));
if(nowdis>dis[i])
{
dis[i]=nowdis;
b[i].x=newx,b[i].y=newy;
}
}
}
T*=r;//降温
}
int ans=0;
double dmax=-1;
for(int i=1;i<=Num;i++)
if(dmax<dis[i]) dmax=dis[i],ans=i;
printf("The safest point is (%.1lf, %.1lf).\n",b[ans].x,b[ans].y);
}
int main()
{
srand((unsigned)time(NULL));
int t;
scanf("%d",&t);
while(t--)
work();
return 0;
}