342 字
2 分钟
BZOJ 1013 [JSOI2008]球形空间产生器sphere 高斯消元

Description#

 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。现在,你被困在了这个n维球体中,你只知道球 面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。

Input#

 第一行是一个整数n(1<=N=10)。接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。每一个实数精确到小数点 后6位,且其绝对值都不超过20000。

Output#

 有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。每个实数精确到小数点 后3位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。

Sample Input#

2
0.0 0.0
-1.0 1.0
1.0 0.0

Sample Output#

0.500 1.500

题解#

直接列方程 到每个点距离相等
手动化简一下 就出来了

BZOJ 竟然不能多输出一个空格(气)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double c[20],a[15][15],b[15],x[15],d;
int n;
void gauss(){
    int im,num=1;
    for(int k=1;k<=n;k++,num++){
        im=k;
        for(int i=k+1;i<=n;i++)
            if(fabs(a[i][k])>fabs(a[im][k]))
                im=i;
        if(im!=k){
            for(int i=k;i<=n;i++)
                swap(a[num][i],a[im][i]);
            swap(b[num],b[im]);
        }
        if(!a[num][k]){num--;continue;}
        for(int i=num+1;i<=n;i++){
            if(!a[num][k])continue;
            double t=a[i][k]/a[num][k];
            for(int j=k;j<=n+1;j++){
                a[i][j]-=t*a[k][j];
            }
            b[i]-=t*b[k];
        }
    }
    for(int i=n;i>=1;i--){
        for(int j=n;j>=i+1;j--)
            b[i]-=a[i][j]*x[j];
        x[i]=b[i]/a[i][i];
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lf",&c[i]);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%lf",&d);
            a[i][j]=d-c[j];
            b[i]+=d*d-c[j]*c[j];
        }
        b[i]/=2;
    }
    gauss();
    for(int i=1;i<n;i++){
        printf("%.3lf ",x[i]);
    }
    printf("%.3lf",x[n]);
}
BZOJ 1013 [JSOI2008]球形空间产生器sphere 高斯消元
https://www.nekomio.com/posts/18/
作者
NekoMio
发布于
2017-06-19
许可协议
CC BY-NC-SA 4.0