[JSOI2008]球形空间产生器

题目描述

有一个球形空间产生器能够在 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;
}

猜你喜欢

转载自blog.csdn.net/sjzezwzy/article/details/80869111