可以证明目标函数为凸函数,有唯一机值点。因此直接使用梯度下降法求极值,注意学习率需要衰减。
class Solution {
public:
double getMinDistSum(vector<vector<int>>& positions) {
double eps = 1e-7;
double alpha = 1.0;
double decay = 1e-3;
double x = 0.0, y = 0.0;
for (auto & position : positions) {
x += position[0];
y += position[1];
}
int n = positions.size();
x = x / n;
y = y / n;
// 计算服务中心 (xc, yc) 到客户的欧几里得距离之和
auto getDist = [&](double xc, double yc) {
double ans = 0;
for (const auto& pos: positions) {
ans += sqrt((pos[0] - xc) * (pos[0] - xc) + (pos[1] - yc) * (pos[1] - yc));
}
return ans;
};
while (true) {
double x_prev = x, y_prev = y;
double dx = 0.0, dy = 0.0;
for (auto & pos : positions) {
dx += (x - pos[0]) / (sqrt((x - pos[0]) * (x - pos[0]) + (y - pos[1]) * (y - pos[1])) + eps);
dy += (y - pos[1]) / (sqrt((x - pos[0]) * (x - pos[0]) + (y - pos[1]) * (y - pos[1])) + eps);
}
x -= alpha * dx;
y -= alpha * dy;
alpha *= (1.0 - decay);
if (sqrt((x - x_prev) * (x - x_prev) + (y - y_prev) * (y - y_prev)) < eps) {
break;
}
}
return getDist(x, y);
}
};