概述
高斯消元是线性代数中的一个算法,可以用来为线性方程组求解。
基本步骤
-
构造原矩阵为三角形格式
[a[1][1] * x[1] + a[1][2] * x[2] + ... + a[1][n] * x[n] = y'[1]\ 0 * x[1] + a[2][2] * x[2] + ... + a[2][n] * x[n] = y'[2]\ 0 * x[1] + 0 * x[2] + ... + a[3][n] * x[n] = y'[3]\ ...\ 0 * x[1] + 0 * x[2] + ... + a[n][n] * x[n] = y'[n]\ 0 * x[1] + 0 * x[2] + ... + 0 * x[n] = y'[n + 1]\ ...\ 0 * x[1] + 0 * x[2] + ... + 0 * x[n] = y'[m]\ ] -
从第n行开始逆推,一步一步将(a[i][j](i<j))也变换为0。
因为第n行为(a[n][n] * x[n] = y'[n]),则(x[n] = y'[n] / a[n][n])。
第n-1行为(a[n-1][n-1] * x[n - 1] + a[n][n] * x[n] = y'[n - 1])。我们将得到的(x[n])代入,即可计算出(x[n-1])。
同样的依次类推就可以得到所有的(x[1]..x[n])。
-
关于多解和无解的判定
**无解: **当在求出的上三角矩阵中出现了 (a[i][1] = a[i][2] = ... = a[i][n] = 0), 但是(y'[i] != 0)时,产生了矛盾,即出现了无解的情况。
**多解: **当等式两边出现(0*X[i]=0)时,显然(X[i])可以取无穷多个值,此时多解。
代码模板
#include<bits/stdc++.h>
#define M 505
#define db double
using namespace std;
int n,m;
db A[M<<1][M],ans[M];
const db eps=1e-7;
void Swap(int i,int j){
for(int k=1;k<=n+1;k++)
swap(A[i][k],A[j][k]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
for(int j=1;j<=n+1;j++)
scanf("%lf",&A[i][j]);
for(int i=1;i<=n;i++){
int id=i;
for(int j=i+1;j<=m;j++)//找到最大的绝对值,保证精度
if(abs(A[id][i])<abs(A[j][i]))
id=j;
if(id!=i)Swap(id,i);
if(abs(A[i][i])<eps)return puts("Many solutions"),0;
db div=A[i][i];
for(int j=i;j<=n+1;j++)A[i][j]/=div;//一次构造三角形格式
for(int j=i+1;j<=m;j++){
for(int q=i+1;q<=n+1;q++)
A[j][q]-=A[i][q]*A[j][i];
A[j][i]=0;
}
}
for(int i=1;i<=m;i++)//判断是否无解
if(abs(A[i][n+1])>eps){
bool flag=0;
for(int j=1;j<=n&&!flag;j++)
if(abs(A[i][j])>eps)flag=1;
if(!flag)return puts("No solutions"),0;
}
for(int i=n;i>=1;i--){//回带
db val=A[i][n+1];
for(int j=n;j>i;j--)
val-=ans[j]*A[i][j];
ans[i]=val/A[i][i];
}
for(int i=1;i<=n;i++)printf("%d
",(int)(ans[i]+0.5));
return 0;
}