procedure2012
It's not worth it to know you're not worth it!

[关键字]:随机化搜索 模拟退火

[题目大意]:在一个给定的矩形中有一些点,找到一个点距所有点的最小距离最短。

//==============================================================================

[分析]:用模拟退火的方法,其实不是标准的模拟退火因为出于时间等因素考虑,并没有加入以一定概率接受稍差解,而只有退火过程。大体步骤:

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;
}



posted on 2012-03-28 10:20  procedure2012  阅读(494)  评论(0编辑  收藏  举报