先贴一段百科
数学上,高斯消元法,是线性代数规划中的一个算法,可用来为线性方程组求解。但其算法十分复杂,不常用于加减消元法,求出矩阵的秩,以及求出可逆方阵的逆矩阵。不过,如果有过百万条等式时,这个算法会十分省时。一些极大的方程组通常会用迭代法以及花式消元来解决。当用于一个矩阵时,高斯消元法会产生出一个“行梯阵式”。高斯消元法可以用在电脑中来解决数千条等式及未知数。
计算机实现高斯消元法其实利用了矩阵的性质,关于矩阵和行列式的性质见某度百科:
行列式 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