题意
已知 n+1 n + 1 个点的坐标,求球心坐标
题解
我们可以通过
2−n
2
−
n
个点,与第一个点列出方程组
即
(xi,1−a1)2+(xi,2−a2)2+⋯+(xi,n−an)2=(x1,1−a1)2+(x1,2−a2)2+⋯+(x1,n−an)2
(
x
i
,
1
−
a
1
)
2
+
(
x
i
,
2
−
a
2
)
2
+
⋯
+
(
x
i
,
n
−
a
n
)
2
=
(
x
1
,
1
−
a
1
)
2
+
(
x
1
,
2
−
a
2
)
2
+
⋯
+
(
x
1
,
n
−
a
n
)
2
解出
2(x1,1−xi,1)a1+2(x2,1−xi,2)a2+⋯+2(x1,n−xi,n)an=x21,1+x21,2+⋯+x1,n−x2i,1−x2i,2−x2n,2
2
(
x
1
,
1
−
x
i
,
1
)
a
1
+
2
(
x
2
,
1
−
x
i
,
2
)
a
2
+
⋯
+
2
(
x
1
,
n
−
x
i
,
n
)
a
n
=
x
1
,
1
2
+
x
1
,
2
2
+
⋯
+
x
1
,
n
−
x
i
,
1
2
−
x
i
,
2
2
−
x
n
,
2
2
这样可以列出
n
n
<script type="math/tex" id="MathJax-Element-12">n</script> 个方程,高斯消元解方程就可以啦
代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define eps 1e-6
double a[22][22],f[22];
int n;
void gauss(){
int now=1;
for(int i=1;i<=n+1;i++){
int to=now;for(int j=now+1;j<=n;j++) if(fabs(a[i][to])<fabs(a[i][j])) to=j;
if(fabs(a[i][to])<eps)continue;
if(to!=now) for(int j=i;j<=n+1;j++) swap(a[now][j],a[to][j]);
for(int j=n+1;j>=i;j--) a[now][j]/=a[now][i];
for(int j=1;j<=n;j++)
if(j!=now)
for(int k=n+1;k>=i;k--) a[j][k]-=a[j][i]*a[now][k];
now++;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf",&f[i]);
for(int i=1;i<=n;i++){
a[i][n+1]=0;
for(int j=1;j<=n;j++){
double x;scanf("%lf",&x);
a[i][j]=2*(x-f[j]);a[i][n+1]+=x*x-f[j]*f[j];
}
}
gauss();
printf("%.3lf",a[1][n+1]);for(int i=2;i<=n;i++) printf(" %.3lf",a[i][n+1]);
return 0;
}