高斯消元法
基本性质:
把某一行乘一个非 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)“变为1
for(int i = r + 1; i < n; i++ ) {
// 将下面所有行的第`c`列清成0
if(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若是不等于0
return 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;
}