题解
每当拿到一个坐标p,其和球心坐标a之间有以下关系
有没有觉得等式右边有点熟悉的感觉?
对吧,很明显,如果等式左边我们能搞出定值就可以直接高斯消元解线性方程了
现在再拿一个坐标来,
两个等式相减
现在可以求啦!
因此第2~n+1个坐标减去第一个坐标,就能构成n个线性方程,高斯板子带进去就行了
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
const double eps = 1e-7;
int n, m, K;
double a[N][N];
int Gass(int n) { // a:1~n b:n+1
int c, r;//col row
for (c = 1, r = 1; c <= n; ++c) {
int t = r;
for (int i = r; i <= n; ++i) {
if (fabs(a[i][c]) > fabs(a[t][c]))
t = i; //找到从r~n行里 首元素最大的那一行
}
if (fabs(a[t][c]) < eps) {
continue;
//后面的解全部都是0 不是无解就是无穷解
}
swap(a[t], a[r]);
for (int i = n + 1; i >= c; --i) {
a[r][i] /= a[r][c];
//该行所有元素除以该行首元素系数
}
for (int i = r + 1; i <= n; ++i) {
if (fabs(a[i][c]) > eps) {
for (int j = n + 1; j >= c; --j) {
//必须从后往前 否则 先算首元素会影响后面的计算
a[i][j] -= a[r][j] * a[i][c];
}
}
}
r++;//换下一行
}
if (r != n + 1) {//没有计算到最后一行
for (int i = r; i <= n; ++i) {
if (fabs(a[i][n + 1]) > eps) return 2;//有多解
}
return 0;//无解
}
for (int i = n; i; --i) {
for (int j = i + 1; j <= n; ++j) {
a[i][n + 1] -= a[j][n + 1] * a[i][j];
}
}
return 1;
}
double p[N][N];
int main() {
ios::sync_with_stdio(0);
cin >> n;
for (int i = 0; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
cin >> p[i][j];
}
}
double tmp = 0;//p1^2
for (int i = 1; i <= n; ++i) {
tmp += p[0][i] * p[0][i];
}
for (int i = 1; i <= n; ++i) {
double tmp2 = 0;
for (int j = 1; j <= n; ++j) {
a[i][j] = p[i][j] - p[0][j];
tmp2 += p[i][j] * p[i][j];
}
a[i][n + 1] = (tmp2 - tmp) / 2;
}
Gass(n);
for (int i = 1; i <= n; ++i) {
printf("%.3f ", a[i][n + 1]);
}
return 0;
}