真是巧,刚做完hnoi2013游走,在大视野上乱翻,随手就翻到了这道题,我一看,这不也是高斯消元嘛。。
题意:n维空间中给出n+1个点的坐标,求以这些坐标为球面的球心。N<=10。
由于每个点到球心距离相等,所以方程很好列。但是这里有个技巧,要用一个已知点作为参照,这样一来刚好n个未知数n个方程了。方程就是点到点的距离,把对应维度的差的平方加起来即可,为了减少精度误差可以不开根号。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define LL long long #define DB double #define rep(i,a,b) for(int i=a;i<=b;++i) #define rrep(i,a,b) for(int i=a;i>=b;--i) const int MAXN = 22; void gaoss(DB a[][MAXN], int n) { int c = 1, r = 1, mxr; for (; c <= n; ++c, ++r) { mxr = r; rep(i, r+1, n) if (fabs(a[i][c]) > fabs(a[mxr][c])) mxr = i; if (mxr != r) rep(i, c, n+1) swap(a[mxr][i],a[r][i]); rep(i, r+1, n+1) a[r][i] /= a[r][c]; a[r][c] = 1; rep(i, 1, n) if (i != r) { rep(j, c+1, n+1) a[i][j] -= a[i][c] * a[r][j]; a[i][c] = 0; } } } DB a[MAXN][MAXN]; DB p1[MAXN], p2[MAXN]; int n; int main() { cin >> n; rep(i, 1, n) cin >> p1[i]; rep(i, 1, n) { rep(j, 1, n) { cin >> p2[j]; a[i][j] = 2.0 * (p2[j] - p1[j]); a[i][n+1] += p2[j]*p2[j] - p1[j]*p1[j]; } } gaoss(a, n); rep(i, 1, n) printf("%.3lf%c", a[i][n+1], i!=n?' ':'\n'); return 0; }