平面中给定N个点的坐标(x, y), 找到离点(m, n)最近的一个点。 该点称为这N个点的 费马点。
代码一
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
#define MAX_NUM 128
/*
*http://www.programlife.net/poj-2420-polygon-fermat-point.html
*http://hi.baidu.com/novosbirsk/item/c3631ee832189fd5ea34c910
*http://poj.org/problem?id=2420
*/
typedef struct TagPoint
{
double x;
double y;
}Point;
inline double pt_distance(const Point &a, const Point &b)
{
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double fermat_point(Point pt[], int n, Point &ptres)
{
Point u, v;
double step = 0.0, curlen, explen, minlen;
int i, j, k, idx;
bool flag = false;
u.x = u.y = v.x = v.y = 0.0;
for(int i =0; i < n; ++i)
{
step += fabs(pt[i].x) + fabs(pt[i].y);
u.x += pt[i].x;
u.y += pt[i].y;
}
u.x /= n;
u.y /= n;
while(step > 1e-5)
{
for(k = 0; k < 10; step /= 2, ++k)
for(int i = -1; i <= 1; ++i)
for(j = -1; j <= 1; ++j)
{
v.x = u.x + step*i;
v.y = u.y + step*j;
curlen = explen = 0.0;
for(idx = 0; idx < n; ++idx)
{
curlen += pt_distance(u, pt[idx]);
explen += pt_distance(v, pt[idx]);
}
if(curlen > explen)
{
u = v;
minlen = explen;
flag = 1;
}
}
}
ptres = u;
return flag? minlen: curlen;
}
int main()
{
int n, i;
double res;
Point pt[MAX_NUM], ptres;
while(EOF != scanf("%d", &n))
{
for(int i = 0; i < n; ++i)
scanf("%lf %lf", &pt[i].x, &pt[i].y);
res = fermat_point(pt, n, ptres);
if(res - (int)(res) > 0.5)
printf("%d\n", (int)(res+1));
else
printf("%d\n", (int)res);
}
return 0;
}
代码二
#include <cstdio>
#include <cmath>
#define PRECISION 1e-8
#define N 101
struct POINT {
double x, y;
POINT(double x, double y) :
x(x), y(y) {
}
POINT() :
x(0), y(0) {
}
};
POINT plist[N];
inline double sqr(double x) {
return x * x;
}
double pt_distance(const POINT &p1, const POINT &p2) {
return sqrt(sqr(p1.x - p2.x) + sqr(p1.y - p2.y));
}
double get_all_dis(const POINT &p, int n)
{
double ans = 0.0;
for(int i = 0; i < n; ++i)
ans += pt_distance(plist[i], p);
return ans;
}
int main()
{
int i, n;
scanf("%d", &n);
for(int i = 0; i < n; ++i)
scanf("%lf%lf", &plist[i].x, &plist[i].y);
POINT st = plist[0];
double step = 100, mind = get_all_dis(st, n);
while(step > 0.2)
{
int ok = 1;
while(ok)
{
POINT tmp, nt;
double t;
ok = 0, nt = st;
tmp = POINT(st.x, st.y + step);
t = get_all_dis(tmp, n);
if (t < mind)
mind = t, ok = 1, nt = tmp;
tmp = POINT(st.x, st.y - step);
t = get_all_dis(tmp, n);
if (t < mind)
mind = t, ok = 1, nt = tmp;
tmp = POINT(st.x + step, st.y);
t = get_all_dis(tmp, n);
if (t < mind)
mind = t, ok = 1, nt = tmp;
tmp = POINT(st.x - step, st.y);
t = get_all_dis(tmp, n);
if (t < mind)
mind = t, ok = 1, nt = tmp;
st = nt;
}
step /= 2.0;
}
int ans = (int)(mind+0.5)*100/100;
printf("%d\n", ans);
return 0;
}