1. 程式人生 > >poj 2420 求n個點的費馬點 隨機演算法解決

poj 2420 求n個點的費馬點 隨機演算法解決

還是跟那題poj 1379 run away一樣的做法

改一下最優的方法(到n個點的距離之和)就好了

View Code
//求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;
}


網上的另一種做法,一個點朝四個方向按一定方向搜尋,然後再逐步縮小步長

程式碼寫的簡單多了,但這種做法有時候會錯。。因為只有四個方向,還是上面的做法保險

也貼貼程式碼吧

View Code
#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;
}