注意事项:

  1. 高斯消元代码的 14 行和 17~20 行也可向矩阵行列式那样包装成一个函数并使用 bottomj 优化常数。但因为在 Luogu P2455 [SDOI2006]线性方程组 的测试中对常数的优化不明显,又因为 swap(a[row], a[maxer]) 在高消中只出现一次,这样做也不会是代码结构更清晰,所以不推荐这种写法。

  2. 该高斯消元代码只适用于矩阵行列长度相等,适用于行列长度不相等的版本请见异或高斯消元

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int n;
double a[MAXn + 10][MAXn + 10];
int guass() {
int row = 1;
for (int col = 1; col <= n; ++col) {
double mx = 0; int maxer = -1;
for (int i = row; i <= n; ++i) {
if (mx < abs(a[i][col])) {
mx = abs(a[i][col]);
maxer = i;
}
}
if (sig(mx) == 0) continue;
if (maxer != row) swap(a[row], a[maxer]);
for (int i = 1; i <= n; ++i) {
if (i == row) continue;
double k = a[i][col] / a[row][col];
for (int j = col; j <= n + 1; ++j) {
a[i][j] -= a[row][j] * k;
}
}
++row;
}
bool noans = 0, infans = 0;
if (row <= n) {
for (int i = row; i <= n; ++i) {
if (sig(a[i][n + 1])) {
noans = 1;
break;
}
}
if (noans == 0) infans = 1;
}
if (noans) return 0;
else if (infans) return -1;
else {
for (int i = 1; i <= n; ++i) {
a[i][n + 1] /= a[i][i];
a[i][i] = 1;
}
return 1;
}
}

Luogu P2455 [SDOI2006]线性方程组

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include<bits/stdc++.h>
using namespace std;
const int MAXn = 50;
const double EPS = 1e-8;

template <typename T>
inline void read(T &a) {
char c;for (c = getchar(); (c < '0' || c > '9') && c != '-'; c = getchar());bool f = c == '-';T x = f ? 0 : (c ^ '0');for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) {x = x * 10 + (c ^ '0');}a = f ? -x : x;
}
template <typename T, typename ...Argv>
inline void read(T &a, Argv &...argv) {
read(a), read(argv...);
}

inline int sig(double x) {
if (x < -EPS) return -1;
else if (x > EPS) return 1;
else return 0;
}

int n;
double a[MAXn + 10][MAXn + 10];
int guass() {
int row = 1;
for (int col = 1; col <= n; ++col) {
double mx = 0; int maxer = -1;
for (int i = row; i <= n; ++i) {
if (mx < abs(a[i][col])) {
mx = abs(a[i][col]);
maxer = i;
}
}
if (sig(mx) == 0) continue;
if (maxer != row) swap(a[row], a[maxer]);
for (int i = 1; i <= n; ++i) {
if (i == row) continue;
double k = a[i][col] / a[row][col];
for (int j = col; j <= n + 1; ++j) {
a[i][j] -= a[row][j] * k;
}
}
++row;
}
bool noans = 0, infans = 0;
if (row <= n) {
for (int i = row; i <= n; ++i) {
if (sig(a[i][n + 1])) {
noans = 1;
break;
}
}
if (noans == 0) infans = 1;
}
if (noans) return 0;
else if (infans) return -1;
else {
for (int i = 1; i <= n; ++i) {
a[i][n + 1] /= a[i][i];
a[i][i] = 1;
}
return 1;
}
}

signed main() {
read(n);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n + 1; ++j) {
scanf("%lf", &a[i][j]);
}
}
int res = guass();
if (res == 0) puts("-1");
else if (res == -1) puts("0");
else {
for (int i = 1; i <= n; ++i) {
printf("x%d=%.2lf\n", i, a[i][n + 1]);
}
}
return 0;
}