题目大意:
给出一个n维球体中球面上的 个点的坐标,问n维球体的球心坐标。
每一个坐标为一个实数精确到小数点后6位且其绝对值都不超过20000。
分析:
那么我们设距离为
,球心的
维坐标为
(
)
那么显然对于任意一点i的
维坐标(
),
必然有
显然球面上任意一点到球心的距离相等,
所以我们可以通过相邻两个方程作差变成N个N元一次方程,
因为
那么我们对于点
,显然是有
那么显然
化简一下,可以得到
即可以转换成
那么我们可以将点
,跟点
,通过这种转换变成一个N元一次方程,
总共可以得到N个这种方程,然后高斯消元就好
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define eps 1e-8
#define N 15
using namespace std;
double a[N][N], c[N][N], b[N];
int n;
int main(){
scanf("%d", &n);
for (int i = 1; i <= n + 1; i++)
for (int j = 1; j <= n; j++) scanf("%lf", &a[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++){
c[i][j] = 2 * (a[i][j] - a[i+1][j]);
b[i] += a[i][j] * a[i][j] - a[i+1][j] * a[i+1][j];
}
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++)
if (fabs(c[j][i]) > eps) {
for (int k = 1; k <= n; k++) swap(c[i][k], c[j][k]);
swap(b[i], b[j]);
}
for (int j = 1; j <= n; j++)
if (i != j) {
double rp = c[j][i] / c[i][i];
for (int k = i; k <= n; k++) c[j][k] -= c[i][k] * rp;
b[j] -= b[i] * rp;
}
}
for (int i = 1; i < n; i++) printf("%.3f ", b[i] / c[i][i]);
printf("%.3f", b[n] / c[n][n]);
return 0;
}