学习笔记——高斯消元
高斯消元是用来解决N元一次方程的神奇算法
在手搓多元一次方程的时候,我们会用到消元法和换元法,所以高斯消元也是这样滴
我们可以把N元M项方程写成一个矩阵,如下
\(\left\{\begin{matrix} x_1&+&x_2&+&x_3&=&6\\ x_1&+&2x_2&+&2x_3&=&11\\ x_1&+&4x_2&-&x_3&=&6\\ \end{matrix}\right.\)
变为
\(\begin{bmatrix} 1&1&1&6\\ 1&2&2&11\\ 1&4&-1&6 \end{bmatrix}\)
初等行变换
矩阵以每一行为单位,支持以下运算
1.给其中一行乘上一个非0常数
2.给其中一行加上另一行
3.交换某两行的位置
其正确性类比于手搓消元法qwq
对于上面的例子,我们可以通过初等行变换,先考虑\(x_1\),选择一个\(x_1\)系数不为0的行移动至第一行固定,将其余行的第一项全部消掉
如下
\(\begin{bmatrix} 1&1&1&6\\ 0&1&1&5\\ 0&3&-2&0 \end{bmatrix}\)
然后从第二行开始找一个\(x_2\)系数不为0的固定在第二行,消掉其他行的第二项,以此类推。
\(\begin{bmatrix} 1&0&0&1\\ 0&1&1&5\\ 0&0&-5&-15 \end{bmatrix}\)
\(\begin{bmatrix} 1&0&0&1\\ 0&1&0&2\\ 0&0&-5&-15\\ \end{bmatrix}\)
(解出\(x_1\)=1 , \(x_2\)=2 , \(x_3\)=3)
除了最右一列常数项,左边部分构成了对角矩阵,就可以得出xi了
但是,对于更一般的方程,可能会有其他情况,比如下面这个矩阵
多解
\(\begin{bmatrix} 1&0&0&1\\ 0&0&1&1\\ 0&0&0&0 \end{bmatrix}\)
可以发现\(x_2\)项系数为0,为自由元(即0*\(x_2\)=0恒成立),所以有无数解,\(x_1\),\(x_3\)为主元,有解。
无解
\(\begin{bmatrix} 0&1 \end{bmatrix}\)
恩0*\(x_1\)=1无解
模板:高斯消元法
第i轮找第i列不为0的行,若找不到则为无解
\(Code\):
#include<bits/stdc++.h>
#define N 105
#define eps (1e-8)
#define double long double
using namespace std;
double c[N][N];
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;++i)
for(int j=1;j<=n+1;++j)
cin>>c[i][j];
for(int i=1;i<=n;++i)
{
bool ok=1;
for(int j=i;j<=n;++j)//这个循环的实际含义是,找到一个未被使用的方程,满足第i项不为0
{
if(fabs(c[j][i])>eps)//满足一定精度(不为0)
{
for(int k=1;k<=n+1;++k) swap(c[j][k],c[i][k]);
ok=0;
}
}
if(ok) {cout<<"No Solution"<<endl;goto u;}//这一项没有一行有系数
for(int j=1;j<=n;++j)
{
if(i==j) continue;
double rate=c[j][i]/c[i][i];//按照这一项的比例来消掉这一项
for(int k=1;k<=n+1;++k) c[j][k]-=rate*c[i][k];//同时这一行减去每一项对应值
}
}
for(int i=1;i<=n;++i) cout<<fixed<<setprecision(2)<<c[i][n+1]/c[i][i]<<endl;//对角矩阵输出答案
u:;
return 0;
}