高消一直是ACM中高层次经常用到的算法,虽然线性代数已经学过,但高消求解的问题模型及高消模板的应用变化是高消的最复杂之处。
先介绍一下高消的基本原理:引入互联网czyuan的帖子:
高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵。
高斯消元法的原理是:
若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组。
所以我们可以用初等行变换把增广矩阵转换为行阶梯阵,然后回代求出方程的解。
以上是线性代数课的回顾,下面来说说高斯消元法在编程中的应用。
首先,先介绍程序中高斯消元法的步骤:
(我们设方程组中方程的个数为equ,变元的个数为var,注意:一般情况下是n个方程,n个变元,但是有些题目就故意让方程数与变元数不同)
1. 把方程组转换成增广矩阵。
2. 利用初等行变换来把增广矩阵转换成行阶梯阵。
枚举k从0到equ – 1,当前处理的列为col(初始为0) ,每次找第k行以下(包括第k行),col列中元素绝对值最大的列与第k行交换。如果col列中的元素全为0,那么则处理col + 1列,k不变。
3. 转换为行阶梯阵,判断解的情况。
① 无解
当方程中出现(0, 0, …, 0, a)的形式,且a != 0时,说明是无解的。
② 唯一解
条件是k = equ,即行阶梯阵形成了严格的上三角阵。利用回代逐一求出解集。
③ 无穷解。
条件是k < equ,即不能形成严格的上三角形,自由变元的个数即为equ – k,但有些题目要求判断哪些变元是不缺定的。
这里单独介绍下这种解法:
首先,自由变元有var - k个,即不确定的变元至少有var - k个。我们先把所有的变元视为不确定的。在每个方程中判断不确定变元的个数,如果大于1个,则该方程无法求解。如果只有1个变元,那么该变元即可求出,即为确定变元。
以上介绍的是求解整数线性方程组的求法,复杂度是O(n3)。浮点数线性方程组的求法类似,但是要在判断是否为0时,加入EPS,以消除精度问题。
以上czyuan帖子的基本原理就介绍完了。
--------------------------我对上面的步骤做一下说明-------------------------------------------
高斯消元求解的详细步骤:
1) 不用说了,对增广矩阵先消元,化为行阶梯矩阵。
很多人认为这就行了,但有时存在如下情况:
1 2 3 4 3
0 1 2 3 3
0 0 0 1 2
0 0 0 0 0
消元后的矩阵化为行阶梯,上面主对角线元素的主元并没有连续,还应将第4列和第3列交换才行。
这是网络上很多的模板所没有的,也是造成关键时候出错的根源所在。
所以模板还要增加对列进行检查的代码。
2) 消元完成后,判断是否有解,分三种,无解,有1个解和有无穷多解。
3) 对于有唯一解和有无穷多解的时候,都要回带。
啥是回带? 详细说明之。
1 2 3 4 3 1 2 4 3 3
0 1 2 3 3 0 1 3 2 3
0 0 0 1 2--------》 0 0 1 0 2 ------》消元后的矩阵------发现有无穷解
0 0 0 0 0 0 0 0 0 0
(行阶梯) (交换列)
因为4个变量,才3行,4-3=1> 0 ,有无穷多解啊。
如果第4行不都是0,回带可以求出这个唯一解。如下:
X1 x2 x3 x4 b1
0 x2 x3 x4 b2
0 0 x3 x4 b3
0 0 0 x4 b4
最后1行,有x4=b4;
第3行: x4+x3=b3,已经求出x4=b4了,带入第3行,可求出x3;同理,把x4 x3 带入第2行,还可求出x2;把x4 x3 x2 带入到第1行,可求出x1;
这就是回带。
回带总结:从最后1行,逐一往回带,从最后1行代回到第1行。
最关键的时候到了:当无穷多解时,最后几行都是0;没法回带;而某些题目在无穷多解时还要你求最小或最优解,没办法,就得枚举最后行为0的那几个解;
如:
1 2 4 3 3
0 1 3 2 3
0 0 1 0 2
0 0 0 0 0
可见最后的x4没法解,如果题中给定x4的范围,那就枚举x4,然后回带;枚举1次x4就回带1次得到一组(x1 x2 x3 x4 );然后根据题意找最优的,具体题目具体分析。