题目描述
有一个球形空间产生器能够在 n 维空间中产生一个坚硬的球体。现在,你被困在了这个 nn 维球体中,你只知道球面上 n+1个点的坐标,你需要以最快的速度确定这个 n 维球体的球心坐标,以便于摧毁这个球形空间产生器。
输入格式
第一行是一个整数(1≤N≤10)。接下来的 n+1行,每行有 n 个实数,表示球面上一点的 nn 维坐标。每一个实数精确到小数点后 6 位,且其绝对值都不超过 20000。
输出格式
有且只有一行,依次给出球心的 n 维坐标( n 个实数),两个实数之间用一个空格隔开。每个实数精确到小数点后 3 位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。
解析:
设球心 ,因为球心到点的距离相等。 相邻两式相减将未知数移到左边。
有n个未知项n个方程可以解得圆心的位置。
#include<bits/stdc++.h>
using namespace std;
inline double read() {
char ss = getchar();
int f = 1;
double x = 0;
while (ss < '0' || ss>'9') {
if (ss == '-') {
f = -1;
}
ss = getchar();
}
while (ss >= '0' && ss <= '9') {
x = x * 10 + ss - '0';
ss = getchar();
}
return x * f;
}
double a[20][20], c[20][20]; // c储存系数 b是每一个方程的值
int n;
double eps = 1e-7;
int main() {
n = read();
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]);
c[i][n+1] += a[i][j] * a[i][j] - a[i + 1][j] * a[i + 1][j];// 累加 平方
}
}
//高斯消元
for (int i = 1; i <= n; i++) {
int max = i;
for (int j = i+1; j <= n; j++) {
if (fabs(c[j][i]) > fabs(c[max][i])) max = j; //选最大的避免选到0
}
//因为这个一定有解所以没有判断是否有解的步骤
// 交换
for (int j = 1; j <= n+1; j++) {
swap(c[i][j], c[max][j]);
}
// c[i][n+1]是等式的值
//消元
for (int j = n+1; j >= 1; j--) {
c[i][j] = c[i][j] / c[i][i]; //对角线化1
}
for (int j = 1; j <= n; j++) {
if (j != i) {
double temp = c[j][i] / c[i][i]; // 乘以系第i列化为0
for (int k = 1; k <= n+1; k++) {
c[j][k] -= c[i][k] * temp;
}
}
}
}
for (int i = 1; i <= n; i++) {
printf("%0.3lf ",c[i][n+1]);
}
return 0;
}