高斯消元法
基本性质:
把某一行乘一个非 0 0 0的数 (方程的两边同时乘上一个非 0 0 0数不改变方程的解)
交换某两行 (交换两个方程的位置)
把某行的若干倍加到另一行上去 (把一个方程的若干倍加到另一个方程上去)
算法步骤
枚举每一列c
-
- 找到绝对值最大的一行
-
- 将该行换到最上面
-
- 将该行第1个数变成1
-
- 将下面所有行的第
c
列清成0
- 将下面所有行的第
例题如下:
高斯消元法解线性方程组
代码如下
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 110;
double a[N][N];
int n;
const double eps = 1e-8; //浮点型存在精度误差,容易
/*枚举每一列
- 1. 找到绝对值最大的一行
- 2. 将该行换到最上面(第r行)
- 3. 将该行第1个数变成1
- 4. 将下面所有行的第`c`列清成0*/
int gauss() {int c, r;//首先开始枚举每一列进行“清零”操作for(c = 0, r = 0; c < n; c ++) {int mx_r = r;for(int i = r; i < n; i++) //找到绝对值最大的一行if(fabs(a[i][c]) > fabs(a[mx_r][c]))mx_r = i;if(fabs(a[mx_r][c]) < eps) continue; //判断最大如果为0,那么没有算的必要for(int i = c; i <= n; i++) swap(a[mx_r][i], a[r][i]); //换到第r行for(int i = n; i >= 0; i-- ) a[r][i] /= a[r][c]; //第”首位(c)“变为1for(int i = r + 1; i < n; i++ ) {// 将下面所有行的第`c`列清成0if(fabs(a[i][c]) > eps) //若是=0则没必要操作for(int j = n; j >= c; j--)a[i][j] -= a[i][c] * a[r][j]; //a[r][c]为1,故这样可以消0}r++; //该方程式固定好,进行下一个方程式行的操作}//判断无解和无限解的情况if(r < n) { //这样的话,那么说明未知数方程式个数不足n,则无法构成完美梯形for(int i = r; i < n; i++ )if(fabs(a[i][n]) > eps) //多出的答案bi若是不等于0return 2; //无解return 1; //无限解 0 == 0} //进行上三角矩阵的方程化简for(int i = n - 1; i >= 0; i -- ) { //从后往前,anxn = bn,一步一步推前方的方程式未知数for(int j = i + 1; j < n; j++) //每i到最后只需保留第i个数(1),其它数全清零a[i][n] -= a[i][j] * a[j][n]; //这里第j行的答案已经算出,后续数(清零)的同步操作}return 0; //有唯一解
}int main() {cin >> n;for(int i = 0; i < n; i++ )for(int j = 0; j < n + 1; j++ )cin >> a[i][j];int r = gauss();if(r == 0) {for(int i = 0; i < n; i ++) printf("%.2lf\n", a[i][n]);} else if(r == 1) puts("Infinite group solutions");else puts("No solution");return 0;
}