>Description
有一个球形空间产生器能够在 n 维空间中产生一个坚硬的球体。现在,你被困在了这个 n 维球体中,你只知道球面上 n+1 个点的坐标,你需要以最快的速度确定这个 n 维球体的球心坐标,以便于摧毁这个球形空间产生器。
>Input
第一行是一个整数 n (1<=N=10)。接下来的 n+1 行,每行有 n 个实数,表示球面上一点的 n 维坐标。每一个实数精确到小数点后 6 位,且其绝对值都不超过 20000。
>Output
有且只有一行,依次给出球心的 n 维坐标( n 个实数),两个实数之间用一个空格隔开。每个实数精确到小数点后 3 位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。
>Sample Input
2
0.0 0.0
-1.0 1.0
1.0 0.0
>Sample Output
0.500 1.500
提示:给出两个定义:
球心:到球面上任意一点距离都相等的点。
距离:设两个n为空间上的点A, B的坐标为
(
a
1
,
a
2
,
⋯
,
a
n
)
,
(
b
1
,
b
2
,
⋯
,
b
n
)
(a1,a2,⋯ ,an),(b1,b2,⋯ ,bn)
(a1,a2,⋯ ,an),(b1,b2,⋯ ,bn),则AB的距离定义为:
d
i
s
t
=
(
a
1
−
b
1
)
2
+
(
a
2
−
b
2
)
2
+
⋯
+
(
a
n
−
b
n
)
2
dist = \sqrt{ (a_1-b_1)^2 + (a_2-b_2)^2 + \cdots + (a_n-b_n)^2 }
dist=(a1−b1)2+(a2−b2)2+⋯+(an−bn)2
>解题思路
一道高斯消元
我们设第
i
i
i个点,球心坐标为
x
x
x,有:
Σ
(
a
i
,
j
−
x
j
)
2
=
C
Σ(a_{i,j}-x_{j})^2=C
Σ(ai,j−xj)2=C
其中
C
C
C为所有点到球心的距离的平方,为一个常数
此时依旧看不出是一道高斯消元,所以我们把上下两行
i
i
i和
i
+
1
i+1
i+1之间两两作差,我们就可以得到(简化一下就得到了):
Σ
(
a
i
,
j
2
−
a
i
+
1
,
j
2
−
2
∗
x
j
∗
(
a
i
,
j
−
a
i
+
1
,
j
)
)
=
0
Σ(a_{i,j}^2-a_{i+1,j}^2-2*x_j*(a_{i,j}-a_{i+1,j}))=0
Σ(ai,j2−ai+1,j2−2∗xj∗(ai,j−ai+1,j))=0
然后我们再移项(把常数移到右边):
Σ
(
2
∗
x
j
∗
(
a
i
,
j
−
a
i
+
1
,
j
)
)
=
Σ
(
a
i
,
j
2
−
a
i
+
1
,
j
2
)
Σ(2*x_j*(a_{i,j}-a_{i+1,j}))=Σ(a_{i,j}^2-a_{i+1,j}^2)
Σ(2∗xj∗(ai,j−ai+1,j))=Σ(ai,j2−ai+1,j2)
未知数为
x
j
x_{j}
xj
这样我们就可以得到一个 n n n行有 n n n个元的矩阵,进行高斯消元即可
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define N 15
#define db double
using namespace std;
int n;
db c[N][N], a[N][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]);
c[i][n + 1] += (a[i][j] + a[i + 1][j]) * (a[i][j] - a[i + 1][j]);
}
for (int i = 1; i <= n; i++)
{
int maxn = i;
for (int j = i + 1; j <= n; j++)
if (fabs (c[j][i]) > fabs (c[maxn][i])) maxn = j;
//题目说明了答案保证有解,不需要判断了
for (int j = 1; j <= n + 1; j++)
swap (c[maxn][j], c[i][j]);
for (int j = 1; j <= n; j++)
if (i != j)
{
db temp = c[j][i] / c[i][i];
for (int t = i + 1; t <= n + 1; t++)
c[j][t] -= c[i][t] * temp;
}
}
for (int i = 1; i <= n; i++)
printf ("%.3lf ", c[i][n + 1] / c[i][i]);
return 0;
}