题目描述
有一个球形空间产生器能够在 n维空间中产生一个坚硬的球体。现在,你被困在了这个 n 维球体中,你只知道球面上 n+1个点的坐标,你需要以最快的速度确定这个 n维球体的球心坐标,以便于摧毁这个球形空间产生器。
输入输出格式
输入格式:
第一行是一个整数 n(1<=N=10)。接下来的 n+1,每行有 n个实数,表示球面上一点的 n维坐标。每一个实数精确到小数点后 6 位,且其绝对值都不超过 20000。
输出格式:
有且只有一行,依次给出球心的 n 维坐标( n个实数),两个实数之间用一个空格隔开。每个实数精确到小数点后 3位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。
输入输出样例
输入样例#1:
2
0.0 0.0
-1.0 1.0
1.0 0.0
输出样例#1:
0.500 1.500
分析
一道裸的高斯消元,可设中心坐标为(x1,x2……,xn),每个点到球心距离相等,可通过半径列等式,可消去二次项,这样的话高斯消元做即可,时间50ms。
上代码
#include<bits/stdc++.h>
using namespace std;
double a[20][20],b[20],c[20][20];
int n;
int main(){
cin>>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]);
b[i]+=a[i][j]*a[i][j]-a[i+1][j]*a[i+1][j];
}
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(fabs(c[j][i])>1e-8){
for(int k=1;k<=n;k++) swap(c[i][k],c[j][k]);
swap(b[i],b[j]);
}
}
for(int j=1;j<=n;j++){
if(i==j) continue;
double r=c[j][i]/c[i][i];
for(int k=i;k<=n;k++) c[j][k]-=c[i][k]*r;
b[j]-=b[i]*r;
}
}
for(int i=1;i<n;i++) printf("%.3f ",b[i]/c[i][i]);
printf("%.3f\n",b[n]/c[n][n]);
return 0;
}