【算法学习】高斯消元法
其实也没法写,真要一步步写很复杂。
无非就是依次将每个数减掉系数,最后成为一个单位矩阵。
所以看注释:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
int n; // n 表示方程的个数,即有 n 个变量
double a[104][104]; // a 是增广矩阵,a[i][j] 表示第 i 行第 j 列的元素,矩阵大小为 n x (n+1)
int main(){
ios::sync_with_stdio(false); // 优化输入输出效率
cin >> n; // 输入变量的个数,即 n 阶矩阵
// 输入增广矩阵
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n + 1; j++){
cin >> a[i][j]; // 输入每个系数和常数项(n x n 的系数矩阵加上 n 个常数项)
}
}
// 高斯-约旦消元法
for(int i = 1; i <= n; i++){
int now = i; // 当前正在处理的行(初始为第 i 行)
// 寻找第 i 列的主元(即第 i 列第一个非 0 的元素)
while(a[now][i] == 0 && now <= n){
now++; // 如果当前行的 i 列为 0,则查找下面的行
}
// 如果该列找不到非 0 的主元,则无解
if(now == n + 1){
cout << "No Solution"; // 输出无解提示
return 0;
}
// 交换当前行 i 和找到的主元所在的行 now
for(int j = 1; j <= n + 1; j++){
swap(a[i][j], a[now][j]); // 交换两个行,确保 a[i][i] 非 0
}
// 将当前行的主元 a[i][i] 归一化,令 a[i][i] = 1
double pp = a[i][i];
for(int j = 1; j <= n + 1; j++){
a[i][j] = a[i][j] / pp; // 将这一行所有元素除以 a[i][i]
}
// 对其他行进行消元,使得第 i 列的其余行元素都为 0
for(int j = 1; j <= n; j++){
if(i != j){ // 跳过第 i 行本身
double k = a[j][i]; // 消元系数
for(int m = 1; m <= n + 1; m++){
a[j][m] = a[j][m] - k * a[i][m]; // 消去 a[j][i],使其为 0
}
}
}
}
// 输出解
for(int i = 1; i <= n; i++){
printf("%.2lf\n", a[i][n+1]); // 输出解,保留两位小数
}
return 0;
}