【题目】
题目描述:
有一个球形空间产生器能够在 n n n 维空间中产生一个坚硬的球体。现在,你被困在了这个 n n n 维球体中,你只知道球面上 n + 1 n+1 n+1 个点的坐标,你需要以最快的速度确定这个 n n n 维球体的球心坐标,以便于摧毁这个球形空间产生器。
输入格式:
第一行是一个整数 n n n。
接下来的 n + 1 n+1 n+1 行,每行有 n n n 个实数,表示球面上一点的 n n n 维坐标。每一个实数精确到小数点后 6 6 6 位,且其绝对值都不超过 20000 20000 20000。
输出格式:
有且只有一行,依次给出球心的 n n n 维坐标( n n n 个实数),两个实数之间用一个空格隔开。
每个实数精确到小数点后 3 3 3 位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。
样例数据:
输入
2
0.0 0.0
-1.0 1.0
1.0 0.0
输出
0.500 1.500
备注:
【数据规模】
对于
40
%
40\%
40% 的数据,
1
≤
n
≤
3
1≤n≤3
1≤n≤3
对于
100
%
100\%
100% 的数据,
1
≤
n
≤
10
1≤n≤10
1≤n≤10
【提示】
给出两个定义:
1
1
1、球心:到球面上任意一点距离都相等的点。
2
2
2、距离:设两个
n
n
n 为空间上的点 A, B 的坐标为
(
a
1
,
a
2
,
…
,
a
n
)
,
(
b
1
,
b
2
,
…
,
b
n
)
(a_1, a_2, …, a_n), (b_1, b_2, …, b_n)
(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 + … + (a_n-b_n)^2}
dist=(a1−b1)2+(a2−b2)2+…+(an−bn)2
【分析】
简单说一下推导过程吧
假设有两个点 A ( a 1 , a 2 , … , a n ) (a_1, a_2, …, a_n) (a1,a2,…,an),B ( b 1 , b 2 , … , b n ) (b_1, b_2, …, b_n) (b1,b2,…,bn),球心坐标为 ( x 1 , x 2 , . . . , x n ) (x_1,x_2,...,x_n) (x1,x2,...,xn)
那么容易得到 ( a 1 − x 1 ) 2 + ( a 2 − x 2 ) 2 + . . . + ( a n − x n ) 2 = ( b 1 − x 1 ) 2 + ( b 2 − x 2 ) 2 + . . . + ( b n − x n ) 2 (a_1-x_1)^2+(a_2-x_2)^2+...+(a_n-x_n)^2=(b_1-x_1)^2+(b_2-x_2)^2+...+(b_n-x_n)^2 (a1−x1)2+(a2−x2)2+...+(an−xn)2=(b1−x1)2+(b2−x2)2+...+(bn−xn)2
拆开后再化简可得 ( 2 b 1 − 2 a 1 ) x 1 + ( 2 b 2 − 2 a 2 ) x 2 + . . . + ( 2 b n − 2 a n ) x n = ( b 1 ) 2 + ( b 2 ) 2 + . . . + ( b n ) 2 − ( a 1 ) 2 − ( a 2 ) 2 − . . . − ( a n ) 2 (2b_1-2a_1)x_1+(2b_2-2a_2)x_2+...+(2b_n-2a_n)x_n=(b_1)^2+(b_2)^2+...+(b_n)^2-(a_1)^2-(a_2)^2-...-(a_n)^2 (2b1−2a1)x1+(2b2−2a2)x2+...+(2bn−2an)xn=(b1)2+(b2)2+...+(bn)2−(a1)2−(a2)2−...−(an)2
可以举点小数据来推,比如让 n = 2 n=2 n=2 来推一遍,这样可能好理解一点
容易看出,两个点列等式可以得到一个关于 x x x 的线性方程,这样把所有的点都列一遍,就有 n n n 个方程,用高斯消元就行
应该不算很难吧
【代码】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 105
using namespace std;
int n;
double ans[N],g[N][N],a[N][N];
void Guass()
{
int i,j,k;
for(i=1;i<=n;++i)
{
k=i;
for(j=i+1;j<=n;++j)
if(fabs(g[k][i])<fabs(g[j][i]))
k=j;
swap(g[i],g[k]);
for(j=i+1;j<=n;++j)
for(k=i+1;k<=n+1;++k)
g[j][k]-=g[i][k]*g[j][i]/g[i][i];
}
for(i=n;i;--i)
{
for(j=i+1;j<=n;++j)
g[i][n+1]-=ans[j]*g[i][j];
ans[i]=g[i][n+1]/g[i][i];
}
}
int main()
{
int i,j;
scanf("%d",&n);
for(i=0;i<=n;++i)
for(j=1;j<=n;++j)
scanf("%lf",&a[i][j]);
double temp;
for(i=1;i<=n;++i)
{
temp=0;
for(j=1;j<=n;++j)
{
g[i][j]=-2*a[i-1][j]+2*a[i][j];
temp+=a[i][j]*a[i][j]-a[i-1][j]*a[i-1][j];
}
g[i][n+1]=temp;
}
Guass();
for(i=1;i<=n;++i)
printf("%.3lf ",ans[i]);
return 0;
}