题意求一个多边形的费马点,即到所有顶点距离和最小的那一点。
以前觉得模拟退火好高端的样子,实际就是把点往四个方向移动固定步长,知道不能移动后缩小步长继续移动,也就是随机求一个接近最优并且满足精度的解。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double diy;
struct point
{
diy x,y;
point() {}
point(diy _x,diy _y):x(_x),y(_y) {}
};
double step[4][2]= {0,1,0,-1,-1,0,1,0};
double dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double disall(point a,point *g,int n)
{
int i=0;
double sum=0;
while(n--)
sum+=dis(a,g[i++]);
return sum;
}
double SAnnealing(point *g,int n)
{
point t=g[0];
int flag;
double ret=disall(t,g,n),st;
for(st=100; st>1e-1; st*=0.98)
{
flag=1;
while(flag)
{
flag=0;
for(int i=0; i<4; i++)
{
point now(t.x+step[i][0]*st,t.y+step[i][1]*st);
double nowdis=disall(now,g,n);
if(nowdis<ret)
t=now,flag=1,ret=nowdis;
}
}
}
return ret;
}
int main()
{
int n;
point data[105];
while(~scanf("%d",&n))
{
for(int i=0; i<n; i++)
scanf("%lf%lf",&data[i].x,&data[i].y);
printf("%.0f\n",SAnnealing(data,n));
}
return 0;
}