• AcWing 207. 球形空间产生器 (高斯消元)打卡


    有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。

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

    输入格式

    第一行是一个整数n。

    接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。

    每一个实数精确到小数点后6位,且其绝对值都不超过20000。

    输出格式

    有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。

    每个实数精确到小数点后3位。

    数据保证有解。

    数据范围

    1n101≤n≤10

    输入样例:

    2
    0.0 0.0
    -1.0 1.0
    1.0 0.0
    

    输出样例:

    0.500 1.500



    题意:n维空间,给你n+1个点,这n+1个点都在圆面上,求这个圆心坐标是多少
    思路:首先每个点都在圆面上,点到圆心的距离相等
    点与圆心的方程为 (x-a)^2+(y-b)^2 = r^2
    然后我们可以把这n+1个点带入,得出n+1个式子
    求线性方程组的算法高斯消元,但是我们还要化简成高斯消元所满足的最简式子,我们可以通过相邻两个方程减,可以得出
    2*(a11-a21)x1 + 2*(a12-a22)x2 ......2*(a1n-a2n)xn = a11^2-b11^2 + a12^2-b12^2 ...... a1n^2-b12^2
    得出n个类似的式子
    我们就可以通过高斯消元最后得出答案
    通过化成矩阵最后化成一个最简矩阵,上面就是化简的过程
    我们通过三种初等行变换进行操作来得出的答案
    1,用一个非零的数乘以这行的所有数
    2,把其中一行的x倍加到另一行
    3,交换两行的位置

    #include<bits/stdc++.h>
    #define maxn  100005
    #define mod 1000000007
    #define eps 1e-8
    using namespace std;
    typedef long long ll;
    double d[20][20],a[20][20],b[20];
    int main(){
        ll n;
        cin>>n;
        for(int i=0;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>d[i][j];
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                a[i][j]=2*(d[i-1][j]-d[i][j]);
                b[i]+=d[i-1][j]*d[i-1][j]-d[i][j]*d[i][j];
            }
        }
        
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
                if(fabs(a[j][i])>eps){//我们要选一个系数不为0的数来进行操作,这个精度一般选择在 1e-4到1e-9之间,因为有些是0的数有可能还被认为系数不为0,有些不是0还被认为是0,必须要用精度判断
                    for(int k=1;k<=n;k++){
                        double t=a[i][k];
                        a[i][k]=a[j][k];
                        a[j][k]=t;
                    }
                    double t=b[i];
                    b[i]=b[j];
                    b[j]=t;
                }
            }
    //这个题是保证有解,有可能还有两种情况,如果某一行都为0,那么就有无穷多个解,如果某一行都为0,但是常数不是0,那么就造成 0 = c 的形式,说明方程无解,这另外两种情况都需要自己判断
    for(int j=1;j<=n;j++){ if(i==j) continue; double state=a[j][i]/a[i][i]; for(int k=1;k<=n;k++){ a[j][k]-=state*a[i][k]; } b[j]-=b[i]*state; } } for(int i=1;i<=n;i++){ printf("%.3lf ",b[i]/a[i][i]); } }
    
    
    
     
  • 相关阅读:
    opencv学习笔记(五)镜像对称
    opencv学习笔记(四)投影
    C++文件读写详解(ofstream,ifstream,fstream)
    C++ 提取字符串中的数字
    opencv学习笔记(三)基本数据类型
    opencv学习笔记(二)寻找轮廓
    分别心
    关于bonecp和QuerRunner
    关于AutoCommit
    一个detect问题引发的一系列思考
  • 原文地址:https://www.cnblogs.com/Lis-/p/11098053.html
Copyright © 2020-2023  润新知