高斯消元

题目链接

何为高斯消元

说一句实在的,平时解方程就是一种高斯消元的过程。也许你会觉得没啥神奇的,但我们平时解方程可以说解法很多,路径可能不一样。而高斯消元呢运用编程的语言,其实是一种固定的解法。

高斯消元略不同于平时解方程,他将方程转化成矩阵,因而,进行简简单单的加减乘除即可。

例如原方程为

2x + 3y+4z = 20

x-2y+3z = 6

6x + 4y - 3z = 5

不得不说,运算得好复杂啊。当然我们解方程可能计算量会小一些。

算法流程

我们消元是一步一步消的,因此,最后的矩阵不为0的应是斜着下来,如上图。

1.在消第i个元时,我们需要找主元,要找i这一系数不为0的。

2.暴力消掉其他行的这一个元

3.求答案,将第i行仅存的第i个元的解求出来。

代码难度并不很大,作为一个模板,还是需要掌握。

//n个方程,n个元
for (int i = 1;i <= n; i ++){//枚举消去的第i个元
        int t;
        for (t = i ;!a[t][i] && t <= n; t ++);//确定主方程,这一个方程的第i个元系数不能为0.
        for (int j = 1;j <= n + 1;j ++)//这里把它放到合适位置,我们所构造的最后矩形是斜着下来的。
            swap(a[i][j],a[t][j]);
        for (int j = 1;j <= n ;j ++){
            if (j == i || a[i][i] == 0)
                continue;
            double q = a[j][i] / a[i][i];//消去这一个元
            for (int k = 1;k <= n + 1;k ++)//方程都减去这一个数。
                a[j][k] -= q * a[i][k];
        }
    }

值得注意的是,有一些题目有精度问题,因而就会出错,本题这样写没有问题,但放在GUIDE的编译器上使用就会有精度问题,CB就没问题。机房的GUIDE我用的MinGW-5.1.4。

因此呢,最好还是处理一下精度。

特殊处理

当然,这样一道题目,是肯定有解的,如果方程组数与未知数组数不等,我们就要判断有无解,那么就只是方程是否有自由元了,也就是说方程是否有多个解。一般来说,算法结束后,有一行全是0,那么被消去的未知数可以任意取值,也就是自由元。

//判断是否有多解
bool wrong(){
    for (int i = 1;i <= n;i ++){
        if (a[i][i] != 1)
            return 0;
        int f = 0;
        for (int j = 1;j <= n; j ++){
            if (i != j && a[i][j] != 0)
                f ++;
        }
        if (f)
            return 1;
    }
    return 0;
}

当然这些处理都是基本操作,一般来说没有这么简单,也没有这么轻松让人看出来可以用高斯消元,因为高斯消元的时间复杂度很大,是N三方的,近乎暴力。。。所以说高斯消元一般来说适用的数据基本小于1000.

在这里给一个高端操作的链接

原文地址:https://www.cnblogs.com/lover-fucker/p/13566690.html