题目:
题意:
平面上给你n个点,让你求一个点,到这n点的距离和最小。
题解:
好玄学啊。。伪代码献上
T=100.0; //初始温度
for(int i=0;i<100;i++) //控制迭代次数
{
tar=getPos(); //在x的周围选一个点
E=f(tar)-f(x);
if(E > eps) x=tar; //直接移动
else if(exp(E/T) > random(0,1)) x=tar; //接受移动
T=T*0.99; //降温
}
模拟退火的讲解引自这个up
这个题目明显有一个更优的趋势,我们用模拟退火
代码:
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
const double eps=1e-8;
const double delta=0.98;
const int N=1005;
struct hh{double x,y;hh(double X=0,double Y=0){x=X;y=Y;};}a[N];
int n;double c[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
double pf(double x){return x*x;}
double getdis(double x,double y)
{
double sum=0;
for (int i=1;i<=n;i++)
sum+=sqrt(pf(x-a[i].x)+pf(y-a[i].y));
return sum;
}
double work()
{
double ans=1e18;
double t=100;
hh now=a[1];
while (t>eps)
{
bool fin=1;
while (fin)
{
fin=0;
for (int i=0;i<4;i++)
{
double x=now.x+c[i][0]*t,y=now.y+c[i][1]*t;
double hx=getdis(x,y);
if (hx<ans) {fin=1;now=hh(x,y);ans=hx;}
}
}
t*=delta;
}
return ans;
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
printf("%.0lf\n",work());
}
}