poj 2420 求n个点的费马点 随机算法解决
还是跟那题poj 1379 run away一样的做法
http://www.cnblogs.com/wuyiqi/archive/2011/12/08/2280885.html
改一下最优的方法(到n个点的距离之和)就好了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//求n边形的费马点
//即找到一个点使得这个点到n个点的距离之和最小
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
const double inf = 1e10;
const double pi = acos(-1.0);
const int Rp = 4;//初始时随机选择一些点,不用太多
const int shift = 60;//但是方向一定要多
struct point {
double x,y;
void goto_rand_dir(double key)
{
double d=2*pi*(double)rand()/RAND_MAX;
x+=key*sin(d);
y+=key*cos(d);
}
void Get_Rand_Point(int a,int b)
{
x=rand()%a+1;
y=rand()%b+1;
}
}p[1010],randp[Rp];
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 dis[Rp];
int main()
{
int i,j,x,y,k,m;
srand(time(NULL));
while(scanf("%d",&m)!=EOF)
{
for(i=0;i<m;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
x=10000;y=10000;
double tmp;
for(i=0;i<Rp;i++)
{
dis[i]=inf;
randp[i].Get_Rand_Point(x,y);
tmp=0;
for(j=0;j<m;j++)
{
tmp+=Dis(randp[i],p[j]);
}
if(tmp<dis[i])
dis[i]=tmp;
}
double key=sqrt(1.0*(x*x+y*y));//初始的步长,要保证初始点从该点出发肯定能包括整个区域
while(key>=0.01)
{
for(i=0;i<Rp;i++)
{
for(j=0;j<shift;j++)
{
point cc=randp[i];
cc.goto_rand_dir(key);
if(cc.x<0||cc.y<0||cc.x>x||cc.y>y) continue;
tmp=0;
for(k=0;k<m;k++)
{
tmp+=Dis(cc,p[k]);
}
if(tmp<dis[i]) //如果从i点出发随机移动的点比原来的点更优,则接受该移动
{
dis[i]=tmp;
randp[i]=cc;
}
}
}
key=key*0.6;//可灵活调整
}
for(i=k=0;i<Rp;i++)
if(dis[i]<dis[k])
k=i;
printf("%.0lf\n",dis[k]);
}
return 0;
}
网上的另一种做法,一个点朝四个方向按一定方向搜索,然后再逐步缩小步长
参考自http://hi.baidu.com/perfectcai_/blog/item/65349a48840bc4e382025cc2.html
代码写的简单多了,但这种做法有时候会错。。因为只有四个方向,还是上面的做法保险
也贴贴代码吧
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <cmath>
#define N 128
#define EPS 0.1
using namespace std;
int n;
double x[N], y[N];
double f(double a, double b)
{
int i;
double ans = 0;
for (i=0; i<n; i++)
ans += sqrt((a-x[i])*(a-x[i]) + (b-y[i])*(b-y[i]));
return ans;
}
int main()
{
double ans, step, temp, a, b, ta, tb;
int i;
bool flag;
while (scanf("%d", &n) == 1)
{
for (i=0; i<n; i++)
scanf("%lf%lf", &x[i], &y[i]);
a = x[0];
b = y[0];
ans = f(a, b);
step = 100;
while (step > EPS)
{
flag = 1;
while (flag)
{
flag = 0;
temp = f(a+step, b);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a + step;
tb = b;
}
temp = f(a-step, b);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a - step;
tb = b;
}
temp = f(a, b+step);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a;
tb = b + step;
}
temp = f(a, b-step);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a;
tb = b - step;
}
a = ta;
b = tb;
}
step /= 2;
}
printf("%.0lf\n", ans);
}
return 0;
}