高斯消元

解线性方程组

高斯消元

我们想想人类是如何解线性方程组的,一个例子

\[\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)\,\),看代码容易发现

posted @ 2021-10-19 09:17  嘉年华_efX  阅读(145)  评论(0编辑  收藏  举报