高斯消元
给定 \(n\) 元线性一次方程组。
\[\begin{cases}
a_{1, 1} \cdot x_1 + a_{1, 2} \cdot x_2 + \cdots + a_{1, n} \cdot x_n = b_1 \\
a_{2, 1} \cdot x_1 + a_{2, 2} \cdot x_2 + \cdots + a_{2, n} \cdot x_n = b_2 \\
\cdots \\
a_{n, 1} \cdot x_1 + a_{n, 2} \cdot x_2 + \cdots + a_{n, n} \cdot x_n = b_n \\
\end{cases}
\]
求出方程组的解,或报告无解。
高斯—约旦消元
- 选择未知数 \(x_i\),\(i\in[1,n]\)。
- 选择包含该未知数且未被标记过的方程 \(a_{j, 1} \cdot x_1 + a_{j, 2} \cdot x_2 + \cdots + a_{j, n} \cdot x_n = b_j\),并将该方程标记。
- 将选择的方程同其他方程相加减,消除其他方程的该未知数。
最后得到形如
\[\begin{cases}
a_{1,{k_1}} \cdot x_{k_1} = b_1 \\
a_{2,{k_2}} \cdot x_{k_2} = b_2 \\
\cdots \\
a_{n,{k_n}} \cdot x_{k_n} = b_n \\
\end{cases}
\]
的方程组,\(k_j\) 为选择第 \(j\) 个方程时所对应的 \(i\)。
我们在每次选择时将选择的方程同第 \(i\) 个方程交换,得到形如
\[\begin{cases}
a_{1,1} \cdot x_1 = b_1 \\
a_{2,2} \cdot x_2 = b_2 \\
\cdots \\
a_{n,n} \cdot x_n = b_n \\
\end{cases}
\]
的方程组,对应的解即为
\[\begin{cases}
x_1 = \dfrac{b_1}{a_{1,1}} \\
x_2 = \dfrac{b_2}{a_{2,2}} \\
\cdots \\
x_n = \dfrac{b_n}{a_{n,n}} \\
\end{cases}
\]
方程组的每一未知数项的系数看做一个 \(n\times n\) 的矩阵,会得到对角矩阵。
\[\begin{bmatrix}
a_{1,1} & 0 & 0 & \cdots & 0 \\
0 & a_{2,2} & 0 &\cdots & 0 \\
0 & 0 & a_{3,3} &\cdots & 0 \\
\cdots & \cdots & \cdots & \cdots & \cdots \\
0 & 0 & 0 & \cdots & a_{n,n} \\
\end{bmatrix}
\]
#include <cmath>
#include <iomanip>
#include <iostream>
using namespace std;
#define MAXN 110
const double eps = 1e-7;
int n;
double a[MAXN][MAXN];
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n + 1; j++)
cin >> a[i][j];
for (int i = 1; i <= n; i++) { // 选择未知数
int s = 0;
for (int j = i; j <= n; j++) // 选择包含该未知数的方程
if (fabs(a[j][i]) > eps) {
s = j;
break;
}
if (!s) { // 无解
cout << "No Solution" << endl;
return 0;
}
for (int j = 1; j <= n + 1; j++) swap(a[i][j], a[s][j]);
for (int j = 1; j <= n; j++) { // 加减消掉其他方程的该未知数项
if (j == i) continue;
const double tmp = a[i][i] / a[j][i];
for (int k = 1; k <= n + 1; k++)
a[j][k] *= tmp;
for (int k = 1; k <= n + 1; k++)
a[j][k] -= a[i][k];
}
}
for (int i = 1; i <= n; i++)
cout << fixed << setprecision(2) << a[i][n + 1] / a[i][i] << endl;
return 0;
}