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