跳转至

爬山算法

例题

P4035 [JSOI2008] 球形空间产生器 - 洛谷

给出 \(n+1\)\(n\) 维的点, 求他们所在球的球心

代码
C++
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int __OneWan_2024 = [](){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    return 0;
}();
double a[15][15], ans[15], dist[15], cans[15];
int main() {
    int n;
    cin >> n;
    for (int i = 1 ; i <= n + 1 ; i++) {
        for (int j = 1 ; j <= n ; j++) {
            cin >> a[i][j];
            ans[j] += a[i][j];
        }
    }
    for (int i = 1 ; i <= n ; i++) {
        ans[i] /= n + 1;
    }
    auto get = [&]() {
        double res = 0;
        for (int i = 1 ; i <= n + 1 ; i++) {
            dist[i] = cans[i] = 0;
            for (int j = 1 ; j <= n ; j++) {
                dist[i] += (a[i][j] - ans[j]) * (a[i][j] - ans[j]);
            }
            dist[i] = sqrt(dist[i]);
            res += dist[i];
        }
        res /= n + 1;
        for (int i = 1 ; i <= n + 1 ; i++) {
            for (int j = 1 ; j <= n ; j++) {
                cans[j] += (dist[i] - res) * (a[i][j] - ans[j]) / res;
            }
        }
    };
    auto sa = [&]() {
        for (double t = 50000 ; t >= 1e-4 ; t *= 0.99995) {
            get();
            for (int i = 1 ; i <= n ; i++) {
                ans[i] += cans[i] * t;
            }
        }
    };
    sa();
    for (int i = 1 ; i <= n ; i++) {
        cout << fixed << setprecision(3) << ans[i] << " ";
    }
    return 0;
}