zoukankan      html  css  js  c++  java
  • sss

    <更新提示>

    <第一次更新>


    <正文>

    球形空间产生器(BZOJ 1013)

    Description

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

    Input Format

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

    Output Format

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

    Sample Input

    2
    0.0 0.0
    -1.0 1.0
    1.0 0.0
    

    Sample Output

    0.500 1.500
    

    解析

    易知球心坐标到球上所有点的距离相等,即求一个(n)维空间中的点((x_1,x_2,...,x_n)),使得

    [forall iin[1,n+1] ,sum_{j=1}^{n}(a_{ij}-x_j)^2=d ]

    成立,(d)为一个定值。

    通过将(i=p)(i=p+1)时的两个式子做差,可以得到:

    [sum_{j=1}^{n}(a_{pj}-x_j)^2-sum_{j=1}^{n}(a_{(p+1)j}-x_j)^2=0 \ sum_{j=1}^{n}(a_{pj}^2-2a_{pj}x_j+x_j^2)-sum_{j=1}^{n}(a_{(p+1)j}^2-2a_{(p+1)j}x_j+x_j^2)=0 \ sum_{j=1}^n(a_{pj}^2-a_{(p+1)j}^2-2x_j(a_{pj}-a_{(p+1)j}))=0 \ sum_{j=1}^n2(a_{pj}-a_{(p+1)j})x_j=sum_{j=1}^n(a_{pj}^2-a_{(p+1)j}^2) ]

    这是一个(n)元一次方程,对于(forall pin[1,n]),都可以得到这样的方程,那么我们就得到了(n)(n)元一次方程。对于该问题,使用高斯消元算法求解,其增广矩阵为:

    [left[ egin{array}{cccc|c} 2(a_{11}-a_{21}) & 2(a_{12}-a_{22}) & cdots & 2(a_{1n}-a_{2n}) & sum_{j=1}^{n}(a_{1j}^2-a_{2j}^2) \ 2(a_{21}-a_{31}) & 2(a_{22}-a_{32}) & cdots & 2(a_{2n}-a_{3n}) & sum_{j=1}^{n}(a_{2j}^2-a_{3j}^2) \ vdots & vdots & ddots & vdots & vdots \ 2(a_{n1}-a_{(n+1)1}) & 2(a_{n2}-a_{(n+1)2}) & cdots & 2(a_{nn}-a_{(n+1)n}) & sum_{j=1}^{n}(a_{nj}^2-a_{(n+1)j}^2) \ end{array} ight] ]

    直接高斯消元即可。

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=120;
    const double eps=1e-8;
    int n;
    double a[N][N],b[N],pos[N][N];
    inline void input(void)
    {
        scanf("%d",&n);
        for (int i=1;i<=n+1;i++)
            for (int j=1;j<=n;j++)
                scanf("%lf",&pos[i][j]);
    }
    inline void init(void)
    {
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                a[i][j] = 2 * ( pos[i][j] - pos[i+1][j] ),
                b[i] += pos[i][j] * pos[i][j] - pos[i+1][j] * pos[i+1][j];
    }
    inline bool Gauss(void)
    {
        for (int i=1;i<=n;i++)
        {
            int row=i;
            for (int j=i+1;j<=n;j++)
                if ( fabs(a[j][i]) > fabs(a[row][i]) )
                    row=j;
            if ( fabs(a[row][i]) < eps )
                return false;
            if ( row ^ i )swap(a[i],a[row]) , swap(b[i],b[row]);
            for (int j=1;j<=n;j++)
            {
                if (i==j)continue;
                double rate = a[j][i] / a[i][i];
                for (int k=i;k<=n;k++)
                    a[j][k] -= a[i][k] * rate;
                b[j] -= b[i] * rate;
            }
        }
        return true;
    }
    int main(void)
    {
        input();
        init();
        Gauss();
        for (int i=1;i<n;i++)
            printf("%.3lf ",b[i]/a[i][i]);
        printf("%.3lf
    ",b[n]/a[n][n]);
        return 0;
    }
    

    <后记>

  • 相关阅读:
    TV
    [转载]如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧
    search result
    floating-camera
    HDU 1032.The 3n + 1 problem【注意细节】【预计数据不强】【8月21】
    C语言socket send()数据缓存问题
    Marlin固件之—:基础入门与測试
    java语句顺序有时非常重要
    Android Studio 使用正式签名进行调试
    插入排序、交换排序、选择排序、归并排序、基数排序
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10712918.html
Copyright © 2011-2022 走看看