BZOJ 1013 [球形空间产生器 sphere]

题面

题意

  给出 \(n\) 维球体上的 \(n+1\) 个点 \(A_0 \sim A_n\),求球心位置。

题解

  令球心的第 \(i\) 维坐标为 \(x_i\),第 \(i\) 个点的第 \(j\) 维坐标为 \((A_i)_j\),球体半径为 \(r\),则可以得到方程:

\[\sum_{j=1}^n ((A_i)_j-x_j)^2=r^2\]

  这样的方程共有 \(n+1\) 个,将 \(r^2=\sum_{j=1}^n ((A_0)_j-x_j)^2\) 代入 \(A_1 \sim A_n\) 对应方程的右边:

\[ \begin{aligned} \sum_{j=1}^n ((A_i)_j-x_j)^2&=\sum_{j=1}^n ((A_0)_j-x_j)^2\\ \sum_{j=1}^n (A_i)_j^2-\sum_{j=1}^n2(A_i)_j x_j+\sum_{j=1}^n x_j^2&=\sum_{j=1}^n (A_0)_j^2-\sum_{j=1}^n2(A_0)_j x_j+\sum_{j=1}^n x_j^2\\ \sum_{j=1}^n (2(A_0)_j-2(A_i)_j) x_j&=\sum_{j=1}^n (A_0)_j^2-\sum_{j=1}^n (A_i)_j^2\\ \end{aligned} \]

  用上面的方法可以得到 \(n\)\(n\) 元一次方程,联立方程组,用高斯消元求出 \(x_1 \sim x_n\) 的值。


代码

#include<iostream>
#include<cstdio>
using namespace std;
typedef long double ld;
const int maxn=15;
ld a[maxn][maxn],x[maxn];
void solve(int n,int m){
    int i,j,k,p;
    double t;
    for (i=0;i<n;i++){
        p=i;
        for (j=i+1;j<n;j++) if (a[j][i]>a[p][i])
            p=j;
        for (j=0;j<m;j++) swap(a[i][j],a[p][j]);
        for (j=0;j<n;j++) if (j!=i){
            t=a[j][i]/a[i][i];
            for (k=i;k<m;k++) a[j][k]-=t*a[i][k];
        }
    }
}
int main(){
    int i,j,k,n;
    ld t;
    scanf("%d",&n);
    for (i=0;i<n;i++) scanf("%Lf",&x[i]);
    for (i=0;i<n;i++) for (j=0;j<n;j++){
        scanf("%Lf",&t);
        a[i][j]=2*t-2*x[j];
        a[i][n]+=t*t-x[j]*x[j];
    }
    solve(n,n+1);
    for (i=0;i<n;i++) printf("%.3Lf%c",a[i][n]/a[i][i],i<n-1?' ':'\n');
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Kilo-5723/p/12174352.html