高斯消元法和高斯-约旦消元法都是用来解形如算法
的方程的解的。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; } }