高消一直是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 );然後根據題意找最優的,具體題目具體分析。