BZOJ 1013 球形空间产生器sphere(高斯消元)

Description

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

Input

第一行是一个整数n(1n10)。接下来的 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

Solution

记第i个点的坐标为 (xi,1,xi,2,...,xi,n) , 0in ,球心坐标为 (x1,x2,...,xn)

则由这 n+1 个点到球心距离相同知 j=1n(xi,jxj)2=j=1n(x0,jxj)2,i=1,2,...,n

展开有 j=1n2(xi,jx0,j)xj=j=1n(x2i,jx20,j)

用高斯消元解出 x1,...,xn 即可

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=15;
#define eps 1e-8
int sign(double x)
{
    if(fabs(x)<eps)return 0;
    if(x>eps)return 1;
    return -1;
}
double A[maxn][maxn],x[maxn];
int Gauss(int equ,int var)
{
    int i=1;
    for(;i<=equ;i++)
    {
        int pos=i;
        for(int j=i+1;j<=equ;j++)
            if(sign(abs(A[j][i])-abs(A[pos][i]))>0)pos=j;
        if(pos!=i)
            for(int j=i;j<=var+1;j++)swap(A[i][j],A[pos][j]);
        if(sign(A[i][i])==0)
        {
            i--;
            continue;
        }
        for(int j=i+1;j<=var+1;j++)A[i][j]/=A[i][i];
        A[i][i]=1;
        for(int j=i+1;j<=equ;j++)
            if(sign(A[j][i]))
            {
                for(int k=i+1;k<=var+1;k++)A[j][k]-=A[j][i]*A[i][k];
                A[j][i]=0;
            }
    }
    for(int j=i;j<=equ;j++)
        if(sign(A[j][var+1]))return -1;//无解
    if(i<=var)return 0;//无穷解,自由变元var-i+1个
    for(int i=var;i>=1;i--)
    {
        double temp=A[i][var+1];
        for(int j=i+1;j<=var;j++)temp-=A[i][j]*x[j];
        x[i]=temp/A[i][i];
    }
    return 1;
}
int n;
double a[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            double temp;
            scanf("%lf",&temp);
            A[i][j]=2.0*(temp-a[j]);
            A[i][n+1]+=temp*temp-a[j]*a[j];
        }
    Gauss(n,n);
    for(int i=1;i<=n;i++)printf("%.3f%c",x[i],i==n?'\n':' ');
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值