P4035 [JSOI2008] 球形空间产生器

高斯消元例题

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

√∑(ai,j-bj)2=r(r为半径)

两边同时平方得到∑(ai,j-bj)2=r2

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

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

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

第i+1去减i可以得到∑2bj*(ai,j-ai+1,j)=∑ai,j2-ai+1,j2

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;
}

 

posted @ 2024-06-30 16:16  storms11  阅读(12)  评论(0编辑  收藏  举报