[BZOJ1013][JSOI2008]球形空间产生器sphere 高斯消元

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1013

首先题目给出了定义$dist^2=sum_{i=1}^n(a_i-x_i)^2$。那我们假设有两个点$a$和$b$,用两个式子做差整理可得$$sum_{i=1}^n2*(a_i-b_i)*x_i=sum_{i=1}^na_i^2-b_i^2$$

那么我们把第1个点拿出来和其它n个点做差得出n个方程,就可以用高斯消元了。高斯消元大概就是每一次用一个方程与剩余的方程做差,消去一个未知数,这样做n-1次就可以得到解中的一个未知数,然后依次从最后回带进去,就可以把所有的未知数一个一个解出来。要注意的是为了保证精度误差尽可能小,所选择的拿去消元的方程,应该是我们要消的那个元的系数最大的那个方程。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 int n;
 7 double a[15][15],l[15][15];
 8 void Gauss(){
 9     for(int i=1;i<=n;i++){
10         int t=i;
11         for(int j=i+1;j<=n;j++)
12             if(fabs(l[j][i])>fabs(l[t][i]))
13                 t=j;
14         if(t!=i)
15             for(int j=i;j<=n+1;j++)
16                 swap(l[i][j],l[t][j]);
17         for(int j=i+1;j<=n;j++){
18             double x=l[j][i]/l[i][i];
19             for(int k=i;k<=n+1;k++)
20                 l[j][k]-=l[i][k]*x;
21         }
22     }
23     for(int i=n;i>=1;i--){
24         for(int j=i+1;j<=n;j++)
25             l[i][n+1]-=l[j][n+1]*l[i][j];
26         l[i][n+1]/=l[i][i];
27     }
28 }
29 int main(){
30     scanf("%d",&n);
31     for(int i=1;i<=n+1;i++){
32         for(int j=1;j<=n;j++){
33             scanf("%lf",&a[i][j]);
34             if(i!=1){
35                 l[i-1][j]=2*(a[i][j]-a[1][j]);
36                 l[i-1][n+1]+=a[i][j]*a[i][j]-a[1][j]*a[1][j];
37             }
38         }
39     }
40     Gauss();
41     for(int i=1;i<=n;i++){
42         printf("%.3lf",l[i][n+1]);
43         if(i!=n) putchar(' ');
44     }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/halfrot/p/7522871.html