数学篇之高斯消元

众所周知,高斯消消乐很好玩(并不),并且理解很简单,代码也很“简单”(蒟蒻到听了n遍还是不会写代码,在此写篇博客记下来)

高斯消元:

高斯消元是用来解线性方程组的,即把一个方程组的系数与方程右边的数写成一个矩阵,再解这个矩阵对应的行列式的值,就可以快速的求解

一个行列式有如下几种初等变换:

1.交换两行(列),行列式的值变号。

2.某行(列)的所有数,同时乘上k,行列式的值不变

3.某行(列)的所有数同时加上a,行列式的值不变

so高斯消元应该怎么消呢?

(高斯消元以列为单位消)

step1:先将第一行第一列的数化为1,并且同一行的数做相同变换

step2:再将其余行的第一列化为0(通过加/减1的k倍),并且同一行的数做相同变换

step3:这时,第一行就处理完了,再将原本的第二行视作新的第一行,且新的第一列为原本的第二列(就是把原来矩阵的第一行第一列扔掉),做相同的变换,一直处理到原本的第n-1行,这样矩阵就消完了。接下来就是回带求解

当然,如果有一行全是0的时候会出现无解或有无穷多解,要特判。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,mo=100000007;
double a[1001][1001];
int main()
{    bool sc=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n+1;j++)
         scanf("%lf",&a[i][j]);
     int bj,flag=0;
     for(int i=1;i<=n;i++)
       {bj=i;
          while(a[bj][i]==0&&bj<=n)
          bj+=1;
          if(bj==n+1){ flag=1;continue;
          }
          for(int j=1;j<=n+1;j++)swap(a[i][j],a[bj][j]);//交换
          double kk=a[i][i];//确保对角线上的数是1
          for(int j=1;j<=n+1;j++)
           {a[i][j]/=kk;//其余数跟着处理
           }
          for(int j=1;j<=n;j++)
          {if(i!=j){double k=a[j][i];//k=这行第一个数
               for(int m=1;m<=n+1;m++)
               {a[j][m]-=k*a[i][m];//此行所有的数减去第一个数*k
               }
             }
           }
          if(i==n)//消完输出
          {for(int j=1;j<=n;j++)
           {for(int m=1;m<=n+1;m++)
             cout<<a[j][m]<<" ";
             cout<<endl;
             sc=1;
           }
          }
       }
       if(!sc)printf("False");
}

吐血三升后肝出来的高消

高斯消消乐真好玩QwQ

 

猜你喜欢

转载自www.cnblogs.com/lcez56jsy/p/10673602.html