【模板】高斯(约旦)消元
高斯消元
运用增广矩阵的三种初等行变换,求解n元线性方程组的算法。如果先消得阶梯形矩阵(向前步骤),再通过回代(向后步骤)解出简化阶梯形矩阵,称为高斯消元法;若直接以含有主元的行消去其余方程中的该项,称为约旦-高斯消元法。
两种方法的时间复杂度相同,区别在于约旦消元没有回代过程,代码简单,而高斯消元实际执行次数较少,效率更快。
代码:
//高斯消元
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define maxn 110
const double eps(1e-7);
using namespace std;
double A[maxn][maxn];
int n;
void print() {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n + 1; ++j) cout << A[i][j] << " ";
cout << endl;
}
cout << endl;
}
void Gause() {
for (int k = 1; k <= n; ++k) {
int mxp = k;
for (int i = k + 1; i <= n; ++i) //确认系数
if (abs(A[i][k]) > abs(A[mxp][k])) mxp = i;
if (abs(A[mxp][k]) < eps)
puts("No Solution"), exit(0);
for (int i = 1; i <= n + 1; ++i) //对换
swap(A[mxp][i], A[k][i]);
for (int i = k + 1; i <= n; ++i) {//消元
double p = A[i][k] / A[k][k];
for (int j = 1; j <= n + 1; ++j)
A[i][j] -= p * A[k][j];
}
}
for (int k = n; k; --k) {
if (abs(A[k][k]) < eps)
puts("No Solution"), exit(0);
A[k][n+1] /= A[k][k];//x_k得解
for (int i = 1; i < k; ++i) {//回代
A[i][n+1] -= A[i][k] * A[k][n+1];
}
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n + 1; ++j) cin >> A[i][j];
Gause();
for (int i = 1; i <= n; ++i) printf("%.2lf\n", A[i][n+1]);
return 0;
}
//约旦消元
#include <iostream>
#include <algorithm>
#include <cstdio>
const int maxn(110);
const double eps(1e-7);
using namespace std;
double a[maxn][maxn];
int n;
bool Jordan() {
for (int k = 1; k <= n; ++k) {
int mxp = k;
for (int i = k + 1; i <= n; ++i)//选取绝对值最大的行作为该主元的代表行,称为部分主元法
if (abs(a[i][k]) > abs(a[mxp][k])) mxp = i;
if (abs(a[mxp][k]) < eps) return false;
for (int i = 1; i <= n + 1; ++i) swap(a[k][i], a[mxp][i]);
for (int i = 1; i <= n; ++i) {//消去每个方程中的该项
if (i == k) continue;
double t = a[i][k] / a[k][k];
a[i][k] = 0;
for (int j = k + 1; j <= n + 1; ++j)
a[i][j] -= a[k][j] * t;
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n + 1; ++j) cout << a[i][j] << " ";
cout << endl;
}
return true;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n + 1; ++j) scanf("%lf", &a[i][j]);
if (Jordan())
for (int i = 1; i <= n; ++i) printf("%.2lf\n", a[i][n+1]/a[i][i]);
else puts("No Solution");
return 0;
}