P4035 [JSOI2008]球形空间产生器

题目描述

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

输入格式

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

输出格式

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

输入输出样例

输入 #1
2
0.0 0.0
-1.0 1.0
1.0 0.0
输出 #1
0.500 1.500

说明/提示

提示:给出两个定义:

  1. 球心:到球面上任意一点距离都相等的点。
  2. 距离:设两个n为空间上的点A, B的坐标为(a1,a2,⋯,an),(b1,b2,⋯,bn)(a_1, a_2, \cdots , a_n), (b_1, b_2, \cdots , b_n)(a1,a2,,an),(b1,b2,,bn),则AB的距离定义为:dist=(a1−b1)2+(a2−b2)2+⋯+(an−bn)2dist = \sqrt{ (a_1-b_1)^2 + (a_2-b_2)^2 + \cdots + (a_n-b_n)^2 }dist=(a1b1)2+(a2b2)2++(anbn)2

思路

求圆心,对每一组数据,可列出(x1-a[i][1])^2+(x2-a[i][2])^2+…+(xn-a[i][n])^2=(x1-a[i+1][1])^2+(x2-a[i+1][2])^2+…+(xn-a[i+1][n])^2;

由此我们可以化简出xi的系数为-2*a[x][i]+2*a[x+1][i]。

因此我们可以建立多元一次方程并高斯消元。

代码

#include<bits/stdc++.h>
using namespace std;
double a[17][17],b[17][17];
int n;
void build(int x,int y){
    for(int i=1;i<=n;i++) a[x][i]=b[y][i]*2-b[x][i]*2,a[x][n+1]+=-(b[x][i]*b[x][i]-b[y][i]*b[y][i]);
    return ;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n+1;i++)
        for(int j=1;j<=n;j++)
            scanf("%lf",&b[i][j]);
    for(int i=1;i<=n;i++) build(i,i+1);
    int pl;
    for(int i=1;i<=n;i++){
        pl=i;
        while(a[pl][i]==0&&pl<=n) pl++;
        if(pl==n+1){printf("No Solution\n");return 0;} 
        for(int j=1;j<=n+1;j++) swap(a[i][j],a[pl][j]);
        double k=a[i][i];
        for(int j=1;j<=n+1;j++) 
            a[i][j]/=k;
        for(int j=1;j<=n;j++){
            if(j!=i){
                double ki=a[j][i];
                for(int m=1;m<=n+1;m++)
                    a[j][m]=a[j][m]-ki*a[i][m];
            }
        }
    }
    for(int i=1;i<=n;i++) printf("%.3lf ",a[i][n+1]);
    return 0;
}

 

posted @ 2019-09-08 08:17  wangyiding  阅读(126)  评论(0编辑  收藏  举报