[关键字]:随机化搜索 模拟退火
[题目大意]:在一个给定的矩形中有一些点,找到一个点距所有点的最小距离最短。
//==============================================================================
[分析]:用模拟退火的方法,其实不是标准的模拟退火因为出于时间等因素考虑,并没有加入以一定概率接受稍差解,而只有退火过程。大体步骤:
1、随机出NUM个点
2、枚举步长,并在此步长下让每一个随机的点随即移动一定次数并记录最优值。
3、退火,步长减少。
[代码]:
View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN=100;
const int NUM=30;
const int TUM=30;
const double ZERO=1e-2;
const double det=0.9;
struct node
{
double x,y,dat;
}a[MAXN*20],b[MAXN],ans;
int n,X,Y;
double dis(node c)
{
double sum=1e8;
for (int i=1;i<=n;++i)
if (sum>sqrt((c.x-a[i].x)*(c.x-a[i].x)+(c.y-a[i].y)*(c.y-a[i].y)))
sum=sqrt((c.x-a[i].x)*(c.x-a[i].x)+(c.y-a[i].y)*(c.y-a[i].y));
return sum;
}
void Init()
{
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)
{
b[i].x=rand()%X+1,b[i].y=rand()%Y+1;
b[i].dat=dis(b[i]);
}
// for (int i=1;i<=NUM;++i) printf("%lf %lf %lf\n",b[i].x,b[i].y,b[i].dat);
// printf("//================================================================\n");
}
void Solve()
{
double tmp,T=(X>Y?X:Y)/sqrt((double)n)+1;
node t;
for (double i=T;i>=ZERO;i*=det)
for (int j=1;j<=NUM;++j)
for (int k=1;k<=TUM;++k)
{
tmp=rand();
t.x=b[j].x+cos(tmp)*i;
t.y=b[j].y+sin(tmp)*i;
if (0<=t.x && t.x<=X && 0<=t.y && t.y<=Y)
{
t.dat=dis(t);
if (t.dat>b[j].dat) b[j]=t;
}
}
ans.dat=-1;
for (int i=1;i<=NUM;++i)
if (ans.dat<b[i].dat) ans=b[i];
printf("The safest point is (%.1lf, %.1lf).\n",ans.x,ans.y);
}
int main()
{
freopen("in3.txt","r",stdin);
freopen("out3.txt","w",stdout);
int test;
scanf("%d",&test);
while (test--)
{
Init();
Solve();
}
return 0;
}