用途:高斯消元可以在n3时间复杂范围内,求解含n个方程,n个未知数的多元线性方程组。解的可能有三种:无解、无穷多组解、唯一解。
做法:高斯消元可以通过初等行列变化把增广矩阵转换成阶梯型矩阵,进而求解 n 个线性方程组的解。
初等行列变换:
1.把某一行乘一个非0的数(方程左右两边同乘)
2.交换某两行的位置
3.把某一行的若干倍加到另一行上
经过如上这三种操作,将原来的增广矩阵变成一个上三角的形式
例
线性方程组为:
a11x1 + a12x2 + a13x3 + … + a1nxn = b1
a21x1 + a22x2 + a23x3 + … + a2nxn = b2
…
an1x1 + an2x2 + an3x3 + … + annxn = bn
则增广矩阵为:
a11 a12 a13 ... a1n b1
a21 a22 a23 ... a2n b2
.
.
.
a21 a22 an3 ... ann bn
经过三种初等行列变换,上面的增广矩阵就可以形成一个阶梯型矩阵:
a11 a12 a13 ... a1n b1
a22 a23 ... a2n b2
.
.
.
ann bn
像上面这种阶梯型属于完美阶梯型,如果能化成完美阶梯型,则有唯一解。
解的情况
上三角的形式有三种:完美阶梯型——唯一解、0 = 非零(左边没有未知数,右边的系数非零)——无解、出现了很多 0 = 0 的方程(该方程可以被很多其它的方程表示,这个方程是多余的)—— 无穷多组解
算法步骤
枚举每一列 c:
① 找到列 c 绝对值最大的一行
② 将该行换到最上面
③ 将该行第一个数变成 1 (即第 c 列的数变成 1)
④ 将下面所有行第 c 列消成 0
例
典例:AcWing 883.高斯消元解线性方程组
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 110;
const double eps = 1e-6;
//浮点数存储是有误差的,如果x < eps,我们就认为x = 0
double a[N][N];
int n;
int gauss()
{
int c,r; // c 是列数 r 是行数
for(c = 0,r = 0; c < n; c ++ )
{
int t = r;
for(int i = r; i < n; i ++ ) //枚举每一行
if(fabs(a[i][c]) > fabs(a[t][c])) //找到当前列绝对值最大的一行
t = i;
//当前这一列最大值都为 0,说明这一列所有系数都为0
if(fabs(a[t][c]) < eps) continue;
//把绝对值最大的这行(即第t行)换到当前最上面一行(第r行)
for(int i = c; i <= n ; i ++ ) swap(a[t][i],a[r][i]);
//把当前行(即第r行)的第一个数变成1,即同时除以该行第一个数
//注意这里要从后往前更新,如果先更新第1个数就不对了
for(int i = n; i >= c; i -- ) a[r][i] /= a[r][c];
//把下面所有行的第c列消成0
for(int i = r + 1; i < n; i ++ )
if(fabs(a[i][c]) > eps) //如果已经是0 ,就不用消了
for(int j = n; j >=c; j -- )
a[i][j] -= a[r][j] * a[i][c];
r ++ ;
}
//最终得到方程个数小于n个,说明不是唯一解,需要判断是无解还是无穷多组解
if(r < n)
{
for(int i = r; i < n; i ++ )
if(fabs(a[i][n]) > eps) // 0 = 非零,无解
return 2;
return 1; //有无穷多组解
}
//有唯一解,从下向上回代,依次求解
for(int i = n - 1; i >= 0; i -- )
for(int j = i + 1; j < n; j ++ )
a[i][n] -= a[i][j] * a[j][n];
return 0; //有唯一解
}
int main()
{
cin >> n;
for(int i = 0; i < n; i ++ )
for(int j = 0; j < n + 1; j ++ )
cin >> a[i][j];
int t = gauss();
if(t == 0) //唯一解
{
for(int i = 0; i < n; i ++ ) printf("%.2lf\n",a[i][n]);
}
else if(t == 1) puts("Infinite group solutions"); //无穷多组解
else puts("No solution"); //无解
return 0;
}