1. 程式人生 > >【bzoj1013】[JSOI2008]球形空間產生器sphere

【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]); }
bzoj1013