题面
题意
给出 \(n\) 维球体上的 \(n+1\) 个点 \(A_0 \sim A_n\),求球心位置。
题解
令球心的第 \(i\) 维坐标为 \(x_i\),第 \(i\) 个点的第 \(j\) 维坐标为 \((A_i)_j\),球体半径为 \(r\),则可以得到方程:
\[\sum_{j=1}^n ((A_i)_j-x_j)^2=r^2\]
这样的方程共有 \(n+1\) 个,将 \(r^2=\sum_{j=1}^n ((A_0)_j-x_j)^2\) 代入 \(A_1 \sim A_n\) 对应方程的右边:
\[ \begin{aligned} \sum_{j=1}^n ((A_i)_j-x_j)^2&=\sum_{j=1}^n ((A_0)_j-x_j)^2\\ \sum_{j=1}^n (A_i)_j^2-\sum_{j=1}^n2(A_i)_j x_j+\sum_{j=1}^n x_j^2&=\sum_{j=1}^n (A_0)_j^2-\sum_{j=1}^n2(A_0)_j x_j+\sum_{j=1}^n x_j^2\\ \sum_{j=1}^n (2(A_0)_j-2(A_i)_j) x_j&=\sum_{j=1}^n (A_0)_j^2-\sum_{j=1}^n (A_i)_j^2\\ \end{aligned} \]
用上面的方法可以得到 \(n\) 个 \(n\) 元一次方程,联立方程组,用高斯消元求出 \(x_1 \sim x_n\) 的值。
代码
#include<iostream>
#include<cstdio>
using namespace std;
typedef long double ld;
const int maxn=15;
ld a[maxn][maxn],x[maxn];
void solve(int n,int m){
int i,j,k,p;
double t;
for (i=0;i<n;i++){
p=i;
for (j=i+1;j<n;j++) if (a[j][i]>a[p][i])
p=j;
for (j=0;j<m;j++) swap(a[i][j],a[p][j]);
for (j=0;j<n;j++) if (j!=i){
t=a[j][i]/a[i][i];
for (k=i;k<m;k++) a[j][k]-=t*a[i][k];
}
}
}
int main(){
int i,j,k,n;
ld t;
scanf("%d",&n);
for (i=0;i<n;i++) scanf("%Lf",&x[i]);
for (i=0;i<n;i++) for (j=0;j<n;j++){
scanf("%Lf",&t);
a[i][j]=2*t-2*x[j];
a[i][n]+=t*t-x[j]*x[j];
}
solve(n,n+1);
for (i=0;i<n;i++) printf("%.3Lf%c",a[i][n]/a[i][i],i<n-1?' ':'\n');
return 0;
}