高斯消元

给定 \(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} \]

求出方程组的解,或报告无解。

高斯—约旦消元

  1. 选择未知数 \(x_i\)\(i\in[1,n]\)
  2. 选择包含该未知数且未被标记过的方程 \(a_{j, 1} \cdot x_1 + a_{j, 2} \cdot x_2 + \cdots + a_{j, n} \cdot x_n = b_j\),并将该方程标记。
  3. 将选择的方程同其他方程相加减,消除其他方程的该未知数。

最后得到形如

\[\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;
}
posted @ 2022-09-25 12:14  Network_Error  阅读(34)  评论(0)    收藏  举报