生活随笔
收集整理的這篇文章主要介紹了
高斯消元知识点
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉自?大佬博客
高斯消元快速入門
一、基本描述
學習一個算法/技能,首先要知道它是干什么的,那么高斯消元是干啥的呢?
高斯消元主要用來求解線性方程組,也可以求解矩陣的秩,矩陣的逆。在ACM中是一個有力的數學武器.
它的時間復雜度是n^3,主要與方程組的個數,未知數的個數有關。
那么什么是線性方程組呢??
簡而言之就是有多個未知數,并且每個未知數的次數均為一次,這樣多個未知數組成的方程組為線性方程組。
二、算法過程
其實高斯消元的過程就是手算解方程組的過程,回憶一下小的時候怎么求解方程組:加減消元,消去未知數,如果有多個未知數,就一直消去,直到得到類似kx=b(k和b為常數,x為未知數)的式子,就可以求解出未知數x,然后我們回代,依次求解出各個未知數的值,就解完了方程組。?
換句話說,分兩步:?
1. 加減消元?
2. 回代求未知數值
高斯消元就是這樣的一個過程。?
下面通過一個小例子來具體說明
0.求解方程組
有這樣一個三元一次方程組:?
?
1.消去x
①×(?3)+②①×(?3)+②得到?
0x?y?2z=?40x?y?2z=?4
①+③①+③得到?
0x+3y+2z=80x+3y+2z=8
?
2.消去y
3+③得到?
0x+0y?4z=?4
進而得到?
?
至此,我們已經求解出來了?
z=1?
下一步我們進行回代過程
3.回代求解y
將z= 1帶入 ②,求得?
y=2
進而得到?
?
4.回代求解x
將z=1,y=2??? 帶入①,求得?
x=?1
最終得到?
?
至此,整個方程組就求解完畢了。
三、再解算法
對于方程組,其系數是具體存在矩陣(數組)里的,下面在給出實際在矩陣中的表示(很熟悉就可以跳過不看啦~)
0.求解方程組
?
1.消去x
?
2.消去y
?
3.回代求解y
回代的時候,記錄各個變量的結果將保存在另外一個數組當中,故保存矩陣的數組值不會發生改變,該矩陣主要進行消元過程。?
?
四、再再解算法
說了這么多,其實有一些情況我們還沒有說到。?
通過上述的消元方法,其實我們比較希望得到的是一個上三角陣(省去了最后的val)?
?
下面問題來了:?
Q1:系數不一定是整數啊??
A1:這時候數組就要用到浮點數了!不能是整數!
Q2:什么時候無解啊??
A2:消元完了,發現有一行系數都為0,但是常數項不為0,當然無解啦!比如:?
?
Q3:什么時候多解啊??
A3:消元完了,發現有好幾行系數為0,常數項也為0,這樣就多解了!有幾行為全為0,就有幾個自由元,所謂自由元,就是這些變量的值可以隨意取,有無數種情況可以滿足給出的方程組,比如:?
您說這x??? y??? z不是無數組解嘛
?
Q4:那什么時候解是唯一的啊!?
A4:您做一下排除法,不滿足2和3的,不就是解釋唯一的嘛!其實也就是說我們的系數矩陣可以化成上三角陣。
判斷解的情況:
a) 當化簡后增廣矩陣的秩等于原矩陣的秩且等于 n (行)時(即化簡后為絕對的上三角),有唯一解;
b) 當化簡后增廣矩陣的秩等于原矩陣的秩且小于 n 時,有多組解;
c) 當化簡后增廣矩陣的秩與原矩陣的秩不相等時(增廣矩陣化簡后存在(0,0,0,……,a)的情況),無解。
解釋一下什么是增廣矩陣的秩等于原矩陣的秩:
轉化成階梯形矩陣(也就是上三角形的矩陣)
看非零行有幾行,那么秩 就是幾
?
五、代碼實現
啰里啰嗦說了一堆,想必算法的流程已經熟悉了,代碼如何實現呢??
?
#include<stdio.h>#include<algorithm>#include<iostream>#include<string.h>#include<math.h>using namespace std;const int MAXN=50;int a[MAXN][MAXN];//增廣矩陣int x[MAXN];//解集bool free_x[MAXN];//標記是否是不確定的變元int gcd(int a,int b){if(b == 0) return a; else return gcd(b,a%b);}inline int lcm(int a,int b){return a/gcd(a,b)*b;//先除后乘防溢出}// 高斯消元法解方程組(Gauss-Jordan elimination).(-2表示有浮點數解,但無整數解,//-1表示無解,0表示唯一解,大于0表示無窮解,并返回自由變元的個數)//有equ個方程,var個變元。增廣矩陣行數為equ,分別為0到equ-1,列數為var+1,分別為0到var.int Gauss(int equ,int var){int i,j,k;int max_r;// 當前這列絕對值最大的行.int col;//當前處理的列int ta,tb;int LCM;int temp;int free_x_num;int free_index;for(int i=0;i<=var;i++){x[i]=0;free_x[i]=true;}//轉換為階梯陣.col=0; // 當前處理的列for(k = 0;k < equ && col < var;k++,col++){// 枚舉當前處理的行.// 找到該col列元素絕對值最大的那行與第k行交換.(為了在除法時減小誤差)max_r=k;for(i=k+1;i<equ;i++){if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;}if(max_r!=k){// 與第k行交換.for(j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]);}if(a[k][col]==0){// 說明該col列第k行以下全是0了,則處理當前行的下一列.k--;continue;}for(i=k+1;i<equ;i++){// 枚舉要刪去的行.if(a[i][col]!=0){LCM = lcm(abs(a[i][col]),abs(a[k][col]));ta = LCM/abs(a[i][col]);tb = LCM/abs(a[k][col]);if(a[i][col]*a[k][col]<0)tb=-tb;//異號的情況是相加for(j=col;j<var+1;j++){a[i][j] = a[i][j]*ta-a[k][j]*tb;}}}}// 1. 無解的情況: 化簡的增廣陣中存在(0, 0, ..., a)這樣的行(a != 0).for (i = k; i < equ; i++){ // 對于無窮解來說,如果要判斷哪些是自由變元,那么初等行變換中的交換就會影響,則要記錄交換.if (a[i][col] != 0) return -1;}// 2. 無窮解的情況: 在var * (var + 1)的增廣陣中出現(0, 0, ..., 0)這樣的行,即說明沒有形成嚴格的上三角陣.// 且出現的行數即為自由變元的個數.if (k < var){return var - k; // 自由變元有var - k個.}// 3. 唯一解的情況: 在var * (var + 1)的增廣陣中形成嚴格的上三角陣.// 計算出Xn-1, Xn-2 ... X0.for (i = var - 1; i >= 0; i--){temp = a[i][var];for (j = i + 1; j < var; j++){if (a[i][j] != 0) temp -= a[i][j] * x[j];}if (temp % a[i][i] != 0) return -2; // 說明有浮點數解,但無整數解.x[i] = temp / a[i][i];}return 0;}int main(void){// freopen("in.txt", "r", stdin);// freopen("out.txt","w",stdout);int i, j;int equ,var;while (scanf("%d %d", &equ, &var) != EOF){memset(a, 0, sizeof(a));for (i = 0; i < equ; i++){for (j = 0; j < var + 1; j++){scanf("%d", &a[i][j]);}}int free_num = Gauss(equ,var);if (free_num == -1) printf("無解!\n");else if (free_num == -2) printf("有浮點數解,無整數解!\n");else if (free_num > 0){printf("無窮多解! 自由變元個數為%d\n", free_num);for (i = 0; i < var; i++){if (free_x[i]) printf("x%d 是不確定的\n", i + 1);else printf("x%d: %d\n", i + 1, x[i]);}}else{for (i = 0; i < var; i++){printf("x%d: %d\n", i + 1, x[i]);}}printf("\n");}return 0;}
?
總結
以上是生活随笔為你收集整理的高斯消元知识点的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。