高斯消元
解线性方程组
高斯消元
我们想想人类是如何解线性方程组的,一个例子
\[\begin{cases}
x+y+z=1\cdots(1)\\
x+2y+3z=2\cdots(2)\\
x+2y+2z=3\cdots(3)
\end{cases}
\]
运用小学数学知识,(2)-(3)就可以解出\(\,z\,\),(1)-(3)就可以解出\(\,y+z\,\),依次带回即可解出所以未知数
考虑模拟此过程,我们先将方程组抽象为矩阵,每一位表示方程中一个未知数在某个方程中的系数(我们认为常数项也是一个\(x^0\)的系数)
那么我们只需要使得这个矩阵满足\(\forall i>j , a_{i,j}=0\),即上三角形式
考虑矩阵基本变换:
1.交换行或列
2.行列带系数作差
于是我们只需要每次选定一个元,将矩阵中在它下方同一行系数全部变为0即可
考虑边界情况
一行全为0,无数解
一行常数项不为0,其他全为0,无解
读者自证不难
高斯约旦消元
考虑高斯消元回带不好写,精度也不高,我们消元时直接消成对角形式,就是每行每列都只有一个值不为0
Talk is cheap , show you the code
read_(n);
for(int i(1);i<=n;++i)
for(int j(1);j<=n+1;++j)
cin>>(x[i][j]);
int pl;
double c;
for(int i(pl=1);i<=n;pl=++i)
{
while(x[pl][i]==0.0&&pl<=n) ++pl;
if(pl==n+1) cout<<"No Solution",exit(0);
if(pl!=i) for(int j(i);j<=n+1;++j) swap(x[i][j],x[pl][j]);
c=x[i][i];
for(int j(i);j<=n+1;++j) x[i][j]/=c;
for(int j(i+1);j<=n;++j)
if(x[j][i]!=0.0)
for(int k(n+1);k>=i;--k)
x[j][k]-=x[j][i]*x[i][k];
}
for(int i(n);i>1;--i)
for(int j(i-1);j;--j)
if(x[j][i]!=0.0)
x[j][n+1]-=x[i][n+1]*x[j][i],x[j][i]=0.0;
for(int i(1);i<=n;++i)
printf("%.2f\n",x[i][n+1]);
复杂度\(\,\Theta(n^3)\,\),看代码容易发现