P4035 [JSOI2008] 球形空间产生器

高斯消元例题

题目要求的是球心的 n 维坐标,给了n+1个点的坐标,用二维的圆来思考,n+1个点到圆心的距离相等,可以列出n+1个等式

√∑(a~i,j~-bj)^2^=r(r为半径)

两边同时平方得到∑(a~i,j~-b~j~)^2^=r^2^

因为a~i,j~已知,所以有n+1个二次方程来解n维坐标和r。

考虑学过的算法并没有高效解多个二次方程的方法,只有高斯消元解线性方程组,所以要去掉二次项。

因为有n+1个方程但真正要求的只有n个数,考虑做差消去二次项。

第i+1去减i可以得到∑2b~j~*(a~i,j~-a~i+1,j~)=∑a~i,j~^2^-a~i+1,j~^2^

n个一元一次方程,n个未知数,高斯消元求解即可。

复制代码
#include <bits/stdc++.h>
using namespace std;
double a[20][20],b[20][20];
int n;
void ycl()
{
    for(int i=1;i<=n+1;i++)
    {
        double ans=0;
        for(int j=1;j<=n;j++)
            scanf("%lf",&a[i][j]),ans+=a[i][j]*a[i][j];    
        a[i][n+1]=ans;    
    }        
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            b[i][j]=2*(a[i][j]-a[i+1][j]);
        b[i][n+1]=a[i+1][n+1]-a[i][n+1];
    }    
} 
int main()
{
    scanf("%d",&n);
    ycl();
    for(int i=1;i<=n;i++)
    {
        int mx=i;
        for(int j=i+1;j<=n;j++)
        {
            if(fabs(b[j][i])>fabs(b[mx][i]))mx=j;
        }
        swap(b[i],b[mx]);
        for(int j=1;j<=n;j++)
        {
            if(j==i)continue;
            double div=b[j][i]/b[i][i];
            for(int k=i;k<=n+1;k++)b[j][k]-=b[i][k]*div;
        }
    } 
    for(int i=1;i<=n;i++)
    {
        printf("%.3lf ",-1*b[i][n+1]/b[i][i]); 
    }
    return 0;
}