高斯消元法和高斯-約旦消元法都是用來解形如算法
的方程的解的。spa
高斯消元法 | 高斯-約旦消元法 | |
---|---|---|
有無回代 | 有 | 無 |
能否判無解和無窮解 | 可 | 不可 |
也就是說,普通的高斯消元法須要回代,代碼比較繁瑣,但能夠分辨無解和無窮解;而高斯-約旦消元法則不須要回代,代碼較簡潔 (其實都挺簡潔的) 但在它眼裏無解和無窮解莫得區別。code
都是七下數學書裏的東西~數學
簡稱代入法
好比說,咱們有方程組\(\left\{\begin{matrix} ax+by=c \\ y=dx+e \\ \end{matrix}\right.\),其中 \(a,b,c,d,e\) 都是常數。那麼,咱們就能夠把 \(dx+e\) 代入到第一個方程,獲得方程 \(ax+b(dx+e)=c\),而後求解。
多元一次方程組同理io
簡稱加減法
又好比說,咱們有另外一個方程組\(\left\{\begin{matrix} ax+by=c \\ ax+dy=e \\ \end{matrix}\right.\),\(a,b,c,d,e\)依然都是常數。那麼,咱們就能夠把上式減下式(或下式減上式)獲得方程 \(by-dy=c-e\),而後求解。
又或者,再拿出來一個方程組\(\left\{\begin{matrix} ax+by=c \\ -ax+dy=e \end{matrix}\right.\),\(a,b,c,d,e\)都是常數,那麼,咱們就能夠把上式加下式,獲得方程 \(by+dy=c+e\),而後求解。
多元一次方程組同理table
以一個三元一次方程組爲例。class
咱們以 \(x,y,z\) 的順序一個個消,先消 \(x\)。
首先咱們隨便拎一個方程出(通常拎要消的元的係數的絕對值最大的那個方程,這樣能夠減少精度損失(然鵝我並不知道爲何QwQ)):原理
咱們要保留 \(5x\),而後把另外的方程中的 \(x\) 的係數變爲 \(0\)。
使用加減法。
先拿①式減②式(咱們拎出來的那個) \(\times \frac{3}{5}\)(這樣才能消去 \(x\)):方法
獲得im
再把這個方程做爲新的①式。
而後再以一樣的方法消③式,得
接着,再消 \(y\),拎出③式,而後減一減(②式不用減),得
這時,咱們發現①式只剩下 \(z\) 了,因而咱們能夠解出
而後代入③式,就能夠解得
再把它們代入②式,解得
上面的過程是否是顯得雜亂無章?
那麼讓咱們把他形式化。
先找到 \(x\) 的係數的絕對值最大的方程,放到最前面
用它消掉下面的式子的 \(x\)
解的過程當中若是拎出來的式子要消的元爲 \(0\),則無解或有無窮解(由於拎出來的方程的元的係數的絕對值已經最大了仍是 \(0\),因此其餘的也就都是 \(0\) 了(感性理解下QwQ?))
而後再找到剩下的方程中 \(y\) 的係數的絕對值最大的那個,提上來
而後消掉它下面的式子的 \(y\)
而後一步步代入,解方程。
最後這一步咱們把它叫作回代
代碼實現又有些不一樣。
上面的介紹中是在最後才把係數化爲 \(1\) 的,但實際上,咱們在選好方程的時候,就能夠把係數化爲 \(1\) 了,這樣還能夠減小碼量。
//n表示未知數的數量 //a[i][j]表明第i個方程中第j個未知數的係數(其實和開頭給出的格式同樣啦~),特殊的,a[i][n+1]表示等式的右邊 for(int i=1;i<=n;i++) { int res=i; for(int k=i+1;k<=n;k++) if(Abs(a[k][i])>Abs(a[res][i])) res=k; for(int j=1;j<=n+1;j++) swap(a[i][j],a[res][j]); if(a[i][i]==0){puts("No Solution");return 0;} for(int j=i+1;j<=n+1;j++) a[i][j]/=a[i][i]; a[i][i]=1; for(int k=i+1;k<=n;k++) { for(int j=i+1;j<=n+1;j++) a[k][j]-=a[k][i]*a[i][j]; a[k][i]=0; } } for(int i=n-1;i>=1;i--) for(int k=i+1;k<=n;k++) a[i][n+1]-=a[i][k]*a[k][n+1];
在回代完後掃一遍,若是遇到 \(a_{i,i}=0\) 而 \(a_{i,n+1}=0\) 則有無窮解,若是遇到 \(a_{i,i}=0\) 而 \(a_{i,n+1} \not= 0\) 則無解。
注意,若是一個方程無解則整個方程組都無解,因此要先判無解再判無窮解。
不過好像仍是會被某些毒瘤數據卡掉的說
因此要打壓這種毒瘤題!
仍是這個方程組爲例。
咱們也保留要消的元的係數絕對值最大的那個方程,而後排下順序就是
(注意原本 \(z\) 係數最大應該是 \(5x+y+6z=25\) 的,可是他被 \(x\) 搶走了)
咱們先消 \(x\)。
首先咱們把選出的方程 \(5x+y+6z=25\) 的 \(x\) 的係數化爲 \(1\):
而後呢,把全部的方程都與它相減使其 \(x\) 的係數變爲 \(1\),也是拿一個式子減這個式子乘多少多少,就不細講了:
而後消 \(y\)。
注意除了選擇的那個方程,要把其餘全部的方程的 \(y\) 的係數都變成 \(0\) 哦。
最後消 \(z\):
因而就能獲得答案:
因此和普通高斯消元比起來,高斯-約旦消元真的方便好多
然鵝實現起來好像差很少(((
//n表示未知數的數量 //a[i][j]表明第i個方程中第j個未知數的係數(其實和開頭給出的格式同樣啦~),特殊的,a[i][n+1]表示等式的右邊 for(int i=1;i<=n;i++) { int res=i; for(int k=i+1;k<=n;k++) if(Abs(a[k][i])>Abs(a[res][i])) res=k; for(int j=1;j<=n+1;j++) swap(a[i][j],a[res][j]); if(a[i][i]==0){puts("No Solution");return 0;} for(int j=i+1;j<=n+1;j++) a[i][j]/=a[i][i]; a[i][i]=1; for(int k=1;k<=n;k++) if(k!=i) { for(int j=i+1;j<=n+1;j++) a[k][j]-=a[k][i]*a[i][j]; a[k][i]=0; } }