高斯消元~

用途:高斯消元可以在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

高斯消元~_第1张图片
典例:AcWing 883.高斯消元解线性方程组
高斯消元~_第2张图片

#include 
#include 
#include 

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;
}

你可能感兴趣的:(算法——数学知识,算法,高斯消元,线性方程组)