高斯消元

不会高斯消元 /kk。

高斯消元,就是通过某种操作消元得到答案。

eg:

\[\begin{cases} 3x+5y+z=20\\x-2y+3z=19\\2x-6y+z=6\end{cases} \]

把它变成增广矩阵形式:

\[\begin{bmatrix}3&5&1&&20\\1&-2&3&&19\\2&-6&1&&6\end{bmatrix} \]

怎么把 \(x\) 消掉呢?\(2\) 式是把 \(3\times \normalsize{②}-\normalsize{①}=0x-11y+8z=37\)

那么 \(3\) 式怎么消呢?用 \(3\times \normalsize{③} - 2\times \normalsize{①}=0x-28y+z=-22\)

那么现在增广矩阵变成了:

\[\begin{bmatrix}3&5&1&&20\\0&-11&8&&37\\0&-28&1&&-22\end{bmatrix} \]

接下来我们让 \(-11\) 为主元。

经过消元,变成了:

\[\begin{bmatrix}3&5&1&&20\\0&-11&8&&37\\0&0&213&&1036\end{bmatrix} \]

带回:

\[\begin{cases}3x+5y+z=20\\0x-11y+8z=37\\0x+0y+213z=1036\end{cases} \]

那就是:

\[\begin{cases}3x+5y+z=20\\-11y+8z=37\\213z=1036\end{cases} \]

解得:

\[\begin{cases}x=3\\y=1\\z=6\end{cases} \]

好了,我们手动模拟了高斯消元的过程。我们来总结一下:

  • 每次找到主元 \(x_i\)(通常是系数最大的)。

  • 将未被选择过的行中的该项全部按照系数相应的减去选定的那行的系数(剩下的其他行 \(x_i\) 系数化为 \(0\))。

  • 倒序求解,每次将常数减去已经求出的所有项的解,此时可以求出当前项的解(将已知解带入求未知解)。

代码很简短:

#include <bits/stdc++.h>

using namespace std;

const int N = 110;
const double eps = 1e-6;

int n;
double a[N][N];

bool solve() {
	int r = 0;
	for (int i = 0; i < n; i++) {
		int now = r;
		for (int j = r; j < n; j++) {
			if (fabs(a[j][i]) > fabs(a[now][i])) {
				now = j;
			}
		}
		if (fabs(a[now][i]) < eps) {
			continue;
		}
		for (int j = i; j <= n; j++) {
			swap(a[now][j], a[r][j]);
		}
		for (int j = n; j >= i; j--) {
			a[r][j] /= a[r][i];
		}
		for (int j = r + 1; j < n; j++) {
			if (fabs(a[j][i]) > eps) {
				for (int k = n; k >= i; k--) {
					a[j][k] -= a[r][k] * a[j][i];
				}
			}
		}
		r++;
	}
	if (r < n) {
		return 1;
	}
	for (int i = n - 1; i >= 0; i--) {
		for (int j = i + 1; j < n; j++) {
			a[i][n] -= a[j][n] * a[i][j];
		}
	}
	return 0;
}
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= n; j++) {
			cin >> a[i][j];
		}
	}
	bool t = solve();
	if (!t) {
		for (int i = 0; i < n; i++) {
			cout << fixed << setprecision(2) << a[i][n] << endl;
		}
	} else {
		cout << "No Solution";
	}
	return 0;
}
posted @ 2024-04-19 17:04  ydq1101  阅读(26)  评论(0)    收藏  举报