【bzoj1013】[JSOI2008]球形空间产生器sphere

  题目传送门:bzoj1013

  其实就是设球心在第$ i $维坐标为$ x_i $,第$ i $个点在第$ j $维的坐标为$ a_{i,j} $,然后列一堆方程:

  $ \sum_{i=1}^{n} (x_i-a_{1,i})^2 = \sum_{i=1}^{n} (x_i-a_{2,i})^2 = \sum_{i=1}^{n} (x_i-a_{3,i})^2 = ... =\sum_{i=1}^{n} (x_i-a_{n+1,i})^2 $

  把完全平方拆开减去同类项就成了n个一次方程,直接上高斯消元(其实就是模拟人手工解方程)。

  代码:

#include<cstdio>
#include<cmath>
#define eps 1e-18
double a[20][20],mat[20][20],ans[20];
int n;
int gauss()
{
    int now=1;
    for(int i=1;i<=n;i++){
        int tmp=now;
        for(;tmp<=n;tmp++)
            if(fabs(mat[tmp][i])>eps)break;
        if(tmp>n)break;
        if(now<tmp){
            for(int j=1;j<=n+1;j++){
                double t=mat[now][j]; mat[now][j]=mat[tmp][j]; mat[tmp][j]=t;
            }
        }
        for(int j=now+1;j<=n;j++){
            double t=mat[j][i]/mat[now][i];
            for(int k=1;k<=n+1;k++)
                mat[j][k]-=t*mat[now][k];
        }
        ++now;
    }
    for(int i=now;i<=n;i++)
        if(fabs(mat[i][n+1])>eps)return 0;
    return 1;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%lf",&a[i][j]);
    for(int i=1;i<=n;i++){
        double sum=0;
        for(int j=1;j<=n;j++){
            sum+=a[0][j]*a[0][j]-a[i][j]*a[i][j];
            mat[i][j]=2*(a[0][j]-a[i][j]);
        }
        mat[i][n+1]=sum;
    }
    gauss();
    for(int i=n;i;i--){
        double tmp=mat[i][n+1];
        for(int j=1;j<=n;j++)
            tmp-=ans[j]*mat[i][j];
        ans[i]=tmp/mat[i][i];
    }
    for(int i=1;i<n;i++)
        printf("%.3lf ",ans[i]);
    printf("%.3lf\n",ans[n]);
}
bzoj1013

 

posted @ 2018-12-05 14:19  QuartZ_Z  阅读(142)  评论(0编辑  收藏  举报