#include <cstdio>
#include <cmath>
#include <algorithm>
const double lim=0.999999;
const double eps=1e-2;
const double pi=3.141592653589793;
double tmp,maxx,minx,maxy,miny,lx,ly,dif;
int n,ns,nc;double ans;
using namespace std;
struct point
{
double x,y;
} t[105];
struct seed
{
double x,y,f;
}s[105],a,p;
inline double dis(double x1,double y1,double x2,double y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
inline double ran()
{
return (((double)(rand()%1000+1))/1000.0);
}
void seed()
{
for (int i=0;i<ns;i++)
{
s[i].x=minx+ran()*lx;
s[i].y=miny+ran()*ly;
s[i].f=0;
for (int j=0;j<n;j++)
s[i].f+=dis(s[i].x,s[i].y,t[j].x,t[j].y);
}
}
void find()
{
for (int i=0; i<ns; i++)
{
p=s[i];
for (int j=0; j<nc; j++)
{
double ang=ran()*2*pi;
a.x=p.x+tmp*cos(ang);
a.y=p.y+tmp*sin(ang);
if (a.x<minx||a.x>maxx||a.y<miny||a.y>maxy)
continue;
a.f=0;
for (int k=0; k<n; k++)
a.f=a.f+dis(a.x,a.y,t[k].x,t[k].y);
dif=a.f-s[i].f;//这个是求最小,最大的话改成dif=s[i].f-a.f;
if (dif<0.0) s[i]=a;//较优解
else//接受较差解
{
dif=exp(-dif/tmp);
if (dif>lim) s[i]=a;
}
}
}
}
int main()
{
int i;
scanf("%d",&n);
minx=miny=1e9;
maxx=maxy=0;
for(i=0;i<n;i++)
{
scanf("%lf%lf",&t[i].x,&t[i].y);
minx=min(minx,t[i].x);maxx=max(maxx,t[i].x);//圈定搜索范围
miny=min(miny,t[i].y);maxy=max(maxy,t[i].y);
}
lx=maxx-minx;//搜索区间长度
ly=maxy-miny;
tmp=max(lx,ly)/sqrt(1.0*n);
ns=5,nc=100;
seed();
while (tmp>eps)
{
find();
tmp=tmp*0.90;
}
int k=0;
for (i=1;i<ns;i++)
if (s[k].f>s[i].f) k=i;
printf("%.0lf\n",s[k].f);
return 0;
}
模拟退火——模板
最新推荐文章于 2022-12-10 20:29:20 发布