zoukankan      html  css  js  c++  java
  • 学习笔记——高斯消元

    高斯消元是用来解决N元一次方程的神奇算法

    在手搓多元一次方程的时候,我们会用到消元法和换元法,所以高斯消元也是这样滴

    我们可以把N元M项方程写成一个矩阵,如下

    (left{egin{matrix} x_1&+&x_2&+&x_3&=&6\ x_1&+&2x_2&+&2x_3&=&11\ x_1&+&4x_2&-&x_3&=&6\ end{matrix} ight.)

    变为

    (egin{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的行移动至第一行固定,将其余行的第一项全部消掉

    如下

    (egin{bmatrix} 1&1&1&6\ 0&1&1&5\ 0&3&-2&0 end{bmatrix})

    然后从第二行开始找一个(x_2)系数不为0的固定在第二行,消掉其他行的第二项,以此类推。

    (egin{bmatrix} 1&0&0&1\ 0&1&1&5\ 0&0&-5&-15 end{bmatrix})

    (egin{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了

    但是,对于更一般的方程,可能会有其他情况,比如下面这个矩阵

    多解

    (egin{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)为主元,有解。

    无解

    (egin{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;
    }
    
  • 相关阅读:
    在LINUX中 用Ctrl+z挂起的命令怎么切回到原任务的命令窗口
    Linux cat 命令
    关于awk中NR、FNR、NF、$NF、FS、OFS的说明
    Linux如何在vim里搜索关键字
    Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 D题题解
    AGC043 B题题解
    Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 C题题解
    JOISC2020 自闭记
    Dwango Programming Contest 6th E 题解
    CF1320 Div1 D.Reachable Strings 题解
  • 原文地址:https://www.cnblogs.com/Chtholly/p/10581254.html
Copyright © 2011-2022 走看看