P3389 【模板】高斯消元法 题解
简要题意:
给定一个由 \(n\) 个方程组成的 \(n\) 元方程组。若有唯一解则输出,否则输出 No Solution
.
前置知识:线性代数相关知识。
很明显,这是线性代数中求解 \(Ax = B\) 的模板题。
考虑实现标准做法,即把 \(A \space | \space B\) 化为上三角的形式。
因为唯一解必须是 \(r(A) = r(A \space | \space B) = n\),因此直接利用上三角形式 \(A_{n,n}\) 是否为 \(0\) 就可以判断。为 \(0\),则有无穷解(因为至少最后一行全为零,即有一个基础解系);不为 \(0\),则必有唯一解。
于是对于化为上三角形式的矩阵,一波代入即可。
对于每一行,我们都要先除掉一个系数,然后把按照下面每一行对应列的系数消掉该元。
时间复杂度:\(\mathcal{O}(n^3)\).
#include <bits/stdc++.h>
using namespace std;
const int N = 1e2 + 1;
#define db double
db A[N][N],B[N],x[N];
int n;
int main() {
cin >> n;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++)
cin >> A[i][j];
cin >> B[i];
}
for(int i = 1; i < n; i++) {
int f = 0;
for(int j = i; j <= n; j++)
if(A[i][j]) {f = j; break;}
if(!f) continue;
for(int j = i + 1; j <= n; j++) A[f][j] /= A[f][i];
B[f] /= A[f][i]; A[f][i] = 1;
for(int j = f + 1; j <= n; j++) {
for(int k = i + 1; k <= n; k++) A[j][k] -= A[f][k] * A[j][i];
B[j] -= B[f] * A[j][i]; A[j][i] = 0;
}
}
if(!A[n][n]) return puts("No Solution"),0;
x[n] = B[n] / A[n][n];
for(int i = n - 1; i >= 1; i--) {
db p = 0;
for(int j = i + 1; j <= n; j++) p += A[i][j] * x[j];
x[i] = B[i] - p;
}
for(int i = 1; i <= n; i++)
cout << fixed << setprecision(2) << x[i] << endl;
return 0;
}
简易的代码胜过复杂的说教。