【bzoj1013】[JSOI2008]球形空间产生器sphere
题目传送门:bzoj1013
其实就是设球心在第$ i $维坐标为$ x_i $,第$ i $个点在第$ j $维的坐标为$ a_{i,j} $,然后列一堆方程:
$ \sum_{i=1}^{n} (x_i-a_{1,i})^2 = \sum_{i=1}^{n} (x_i-a_{2,i})^2 = \sum_{i=1}^{n} (x_i-a_{3,i})^2 = ... =\sum_{i=1}^{n} (x_i-a_{n+1,i})^2 $
把完全平方拆开减去同类项就成了n个一次方程,直接上高斯消元(其实就是模拟人手工解方程)。
代码:
#include<cstdio> #include<cmath> #define eps 1e-18 double a[20][20],mat[20][20],ans[20]; int n; int gauss() { int now=1; for(int i=1;i<=n;i++){ int tmp=now; for(;tmp<=n;tmp++) if(fabs(mat[tmp][i])>eps)break; if(tmp>n)break; if(now<tmp){ for(int j=1;j<=n+1;j++){ double t=mat[now][j]; mat[now][j]=mat[tmp][j]; mat[tmp][j]=t; } } for(int j=now+1;j<=n;j++){ double t=mat[j][i]/mat[now][i]; for(int k=1;k<=n+1;k++) mat[j][k]-=t*mat[now][k]; } ++now; } for(int i=now;i<=n;i++) if(fabs(mat[i][n+1])>eps)return 0; return 1; } int main() { scanf("%d",&n); for(int i=0;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&a[i][j]); for(int i=1;i<=n;i++){ double sum=0; for(int j=1;j<=n;j++){ sum+=a[0][j]*a[0][j]-a[i][j]*a[i][j]; mat[i][j]=2*(a[0][j]-a[i][j]); } mat[i][n+1]=sum; } gauss(); for(int i=n;i;i--){ double tmp=mat[i][n+1]; for(int j=1;j<=n;j++) tmp-=ans[j]*mat[i][j]; ans[i]=tmp/mat[i][i]; } for(int i=1;i<n;i++) printf("%.3lf ",ans[i]); printf("%.3lf\n",ans[n]); }