/* 题意:给出N台电脑的位置,找出某个点到N个电脑的距离之和最小 题解:费马点+模拟退火(模板题) 模板题用模拟退火求费马点 */ #include <iostream> #include <cmath> using namespace std; struct point { double x,y; }p[105]; int dir[8][2] = {-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1}; double getdis(point a, point b) { return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } double allDis(int n , point f) { double sum = 0; for(int i = 0 ; i < n ; i++) sum += getdis(p[i],f); return sum; } point fermat(int n) { double step = 0; for (int i = 0 ; i < n ; i++) step += fabs(p[i].x) + fabs(p[i].y); point f; f.x = 0; f.y = 0; for (int i = 0 ; i < n ; i++) f.x += p[i].x , f.y +=p[i].y; f.x /= n; f.y /= n; point t; while(step > 1e-10) { for (int i = 0 ; i < 8 ; i++) { t.x = f.x + dir[i][0]*step; t.y = f.y + dir[i][1]*step; if(allDis(n,t) < allDis(n,f)) f = t; } step *=0.7; //步长改动 } return f; } int main(void) { int n; while (cin >> n) { for(int i=0; i<n; i++) cin >> p[i].x >> p[i].y; double ans = allDis(n, fermat(n)); int t = ans*10; if (t%10 < 5) cout << t/10 << endl; else cout << t/10+1 << endl; } return 0; }