n 边形的费马点, 即某一点到n 边形的n 个顶点距离和最小的点。
模拟退火精度会受损。
模拟退火,就是一种贪心算法,但一定要注意得满足一些类似三角不等式的条件才能使用,否则不就不是损精度的问题了,而是根本上就是错误的。
以求费马点为例:
在平面上我先随便选出一点出发,向上下左右4个方向(这里只是以4方向为例,你也可以设8方向等,对于3维的可以设6方向)每个方向都尝试性的迈一步,这一步的大小为step,在所到的4个新地点选一个到所有点距离和最小的,然后你就走到那个点作为下一步的出发点,直到某一时刻四个方向都不如你当前所占的地点优,这是就将step/=2(除2也是灵活的,你也可以除1.5)之后再重复找四个方向。
不能更新的意义就是在当前step的精度下无法再移动,所以要再次缩小精度。这就像在google地图上找scnu公寓一样,先找到中国,再缩小精度(step/=2),再找到gz,在缩小精度,再找到scnu,再缩小精度,再找到xisan。----参考某blog
算法:
先拿一个点(该算法用n 个顶点的x, y 坐标和的均值所在的点)去计算距离和最小值, 然后拿它的四个方向上的点去测试比较哪个点更优, 不断迭代, 最终得到在精度允许下的费马点.
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <deque>
#include <stack>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <limits.h>
#include <time.h>
using namespace std;
int lowbit(int t){return t&(-t);}
int countbit(int t){return (t==0)?0:(1+countbit(t&(t-1)));}
int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}
#define LL long long
#define PI acos(-1.0)
#define N 110
#define MAX INT_MAX
#define MIN INT_MIN
#define eps 1e-8
#define FRE freopen("a.txt","r",stdin)
struct node{
double x,y;
}p[N];
int n;
double d[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
double dis(node a,node b){
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double dis_all(node a){
int i;
double sum=0;
for(i=0;i<n;i++){
sum+=dis(a,p[i]);
}
return sum;
}
int main(){
while(scanf("%d",&n)!=EOF){
int i,j,k;
for(i=0;i<n;i++)scanf("%lf %lf",&p[i].x,&p[i].y);
node p0=p[0];
double minm=INT_MAX;
double step;
for(step=1000.0;step>eps;step/=2.0){
int flag=1;
while(flag){ //当再也找不到比当前小的就中止循环,把step缩小再找
flag=0;
for(i=0;i<4;i++){
node tmp;
tmp.x=p0.x+d[i][0]*step;
tmp.y=p0.y+d[i][1]*step;
double t=dis_all(tmp);
if(t<minm){
minm=t;
p0=tmp;
flag=1;
}
}
}
}
printf("%.0f\n",minm);
}
return 0;
}