高斯消元思路很简单,就是有m个n元一次的方程组,让我们求解出n个未知数的解。思路就是:每次先把一个方程作为对象,然后和剩下的方程进行消减,将剩下的方程中的某一个未知数的系数变为0,形成一个新的方程。依次消除之后,我们剩下的方程组就是一个倒立直角三角形,最后一个方程只剩下一个未知项的系数,那么我们可以得出这个未知数的解,再往回带,就依次求出了所有的解。
当然,有时候题目给我们的m个方程组是没有解的,比如说当你做完消除的操作之后,发现有的方程,所有未知数的系数都变为了0,但是方程右边的常数并不为0,这种情况下,我们说这个方程组是无解的。
还有一种情况就是,我们做完所有的消除操作之后,回带的时候发现,去掉我们已经知道的未知项,在当前方程仍然还存在两个或两个以上的系数不为零的未知数。那么这时候这个方程的解是有无限个的,我们称这个有无限个解的未知项为方程组的自由元。
大致思路就结束了,在我们会带的时候还有一个优化,在消除操作的时候,对所有的方程都做一次。那么当我们做完消除以后,如果方程组有唯一解,那么我们存储系数的二维矩阵每行就已经只剩一个系数了,我们直接输出方程右边的常数除以这个系数的值就是当前未知数的解了。
上代码:
luogu P4035:球形空间生成器
#include<bits/stdc++.h>
using namespace std;
double a[20][20],c[20][20],b[20];
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n+1;i++){
for(int j=1;j<=n;j++) scanf("%lf",&a[i][j]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) c[i][j]=2*(a[i][j]-a[i+1][j]),
b[i]+=a[i][j]*a[i][j]-a[i+1][j]*a[i+1][j];
}
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(fabs(c[j][i])>1e-8){
for(int k=1;k<=n;k++) swap(c[j][k],c[i][k]);
swap(b[i],b[j]);
}
}
for(int j=1;j<=n;j++){
if(i==j) continue;
double rate=c[j][i]/c[i][i];
for(int k=1;k<=n;k++) c[j][k]-=c[i][k]*rate;
b[j]-=b[i]*rate;
}
}
for(int i=1;i<=n;i++) printf("%.3f ",b[i]/c[i][i]);
cout<<endl;
return 0;
}