zoukankan      html  css  js  c++  java
  • [洛谷P3389][模板]高斯消元法

    先贴一段百科

      数学上,高斯消元法,是线性代数规划中的一个算法,可用来为线性方程组求解。但其算法十分复杂,不常用于加减消元法,求出矩阵的秩,以及求出可逆方阵的逆矩阵。不过,如果有过百万条等式时,这个算法会十分省时。一些极大的方程组通常会用迭代法以及花式消元来解决。当用于一个矩阵时,高斯消元法会产生出一个“行梯阵式”。高斯消元法可以用在电脑中来解决数千条等式及未知数。

    计算机实现高斯消元法其实利用了矩阵的性质,关于矩阵和行列式的性质见某度百科:

          行列式 https://baike.baidu.com/item/%E8%A1%8C%E5%88%97%E5%BC%8F 

          矩阵 https://baike.baidu.com/item/%E7%9F%A9%E9%98%B5/18069

    对于方程来说,有:

    1)两方程互换,解不变;

    2)一方程乘以非零数k,解不变;

    3)一方程乘以数k加上另一方程,解不变

    根据这三项性质, 我们可将方程中的各个未知数消去, 当方程个数和未知数总数相等时, 我们可以通过消元直接得出一个未知数的值, 这个方程一定是可解的.

    对应到行列式, 有行列式的以下性质:

    1)对换行列式中两行的位置,行列式反号

    2)行列式的某一行乘任一非零数 k 等于用这个数乘此行列式

    3)一行加上另一行的k倍,行列式的值不变

    根据这三条性质, 我们一定可以通过一系列流程将行列式转化成一个上三角, 那么也就有了在方程中各个未知数的值.

    具体的操作流程

          1. 用一个非零的数乘矩阵的某一行

          2. 将一行的k倍加到另一行上

          3. 交换矩阵中两行的位置

    其他的代码里都写注释了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 int n;
     8 double a[101][102];
     9 
    10 void solve()
    11 {
    12     int g;
    13     for(int i=1;i<=n;i++)//消元循环,i用于检索对角线上各个点的行列
    14     {
    15         if(!a[i][i])
    16         {
    17             int r=i; //记录当前所在的行
    18             for(r=i+1;r<=n;r++) //寻找当前列上不为零的一行
    19                 if(a[r][i])
    20                 {
    21                     break;
    22                 }
    23             for(int j=1;j<=n+1;j++)
    24                 swap(a[r][j],a[i][j]); //换行
    25         }
    26         /* 接下来利用高斯消元法求解
    27         实际左下的三角形对整个式子的结果无影响,
    28         只需根据它们求上下的比例关系 */
    29         for(int k=i+1;k<=n;k++) //k用于记录需消元的行 
    30             for(int j=n+1;j>=i;j--) //j用于记录该行每个需要变化的,用于计算结果的系数
    31                 {
    32                     a[k][j] -= (a[k][i]/a[i][i])*a[i][j];
    33                 }
    34                 /*
    35                    这里是求出了这一行需要消去的系数和它上面对应的数的
    36                    关系,然后按照这个关系对无需消去的数求差,这里一定
    37                    是按照三角形消的,因为最外层循环的i在改变,从而就改
    38                    变了开始这一“消元”循环的位置,注意用双精
    39                 */
    40     }
    41 
    42     for(int i=n;i>=1;i--) //求解循环,从最后一个解倒推
    43     {
    44         if(!a[i][i])
    45         {
    46             cout<<"No Solution";
    47             return;
    48         }
    49         for(int j=i+1;j<=n;j++)
    50             a[i][n+1] -= a[j][n+1]*a[i][j]; //将解存到等式右边
    51         a[i][n+1]/=a[i][i]; //最后的值除以当前的未知数的系数
    52     }
    53 
    54     for(g=1;g<=n;g++)
    55         printf("%.2lf
    ",a[g][n+1]);
    56 }
    57 
    58 int main()
    59 {
    60     int pl;
    61     ios::sync_with_stdio(false);
    62     cin>>n;
    63     for(int i=1;i<=n;i++)
    64         for(int j=1;j<=n+1;j++)
    65             cin>>a[i][j];
    66     solve();
    67 
    68     return 0;
    69 }

    在这里感谢Moster_Yi神仙的指导QwQ

  • 相关阅读:
    Navicat 回复 psc 文件 Mysql
    android SDK 更新问题完美解决 http://dl-ssl.google.com refused
    利用android来赚钱
    苹果应用 Windows 申请 普通证书 和Push 证书 Hbuilder 个推(2)
    苹果应用 Windows 申请 普通证书 和Push 证书 Hbuilder 个推
    Java version 32转64位
    浅谈Jquery中的bind()、live()、delegate()、on()绑定事件方式
    JavaScript之深浅拷贝
    关于一道JS面试题的思考
    EasyUI-Tooltip(提示框)学习
  • 原文地址:https://www.cnblogs.com/Foggy-Forest/p/12203194.html
Copyright © 2011-2022 走看看