用法
-
输入:一个矩阵,表示一个线性方程组。例如:
⎣⎢⎡241−1111−11150⎦⎥⎤,
表示
⎩⎪⎪⎨⎪⎪⎧2x1−x2+x3=14x1+x2−x3=5x1+x2+x3=0。
-
输出:若方程有唯一解,输出唯一的一组解。如:
⎩⎪⎪⎨⎪⎪⎧x1=1x2=0x3=−1。
算法可以判断无解/有无限组解。
-
效率:时间:O(N3),空间:O(N2)。
做法
step1: 消元
以 ⎣⎢⎡241−1111−11150⎦⎥⎤ 为例,
首先将一至三行中 x1 项系数绝对值最大的一行(即第二行)移到第一行,得:
⎣⎢⎡4211−11−111510⎦⎥⎤。
接着将其他方程中 x1 项的系数化为0。令第二条方程加上第一条的 −21 倍,得:
⎣⎢⎡4011−231−12315−230⎦⎥⎤。
令第三条方程加上第一条的 −41 倍,得:
⎣⎢⎡4001−2343−123455−23−45⎦⎥⎤。
接着消第二个元。
⎣⎢⎡4000−2300234174−23−417⎦⎥⎤。
消第三个元。
⎣⎢⎡4000−2300041740−417⎦⎥⎤。
至此,消元完毕。得:
⎩⎪⎪⎨⎪⎪⎧4x1=4−23x2=0417x3=−417。
step2: 系数化为1
系数化一,将矩阵化为单位矩阵,得:
⎣⎢⎡10001000110−1⎦⎥⎤。
所以,原方程组的解就是:
⎩⎪⎪⎨⎪⎪⎧x1=1x2=0x3=−1。
step3: 检查无解/无穷解
如果在消元时,碰到某一元系数为0,就先跳过。到最后再来看,只要有一个出现 bx=0(b=0) 就是无解,如果都是 0x=0,就是无限组解。
可以发现,对于每个元,需要 O(N2) 的时间来对每一项加减,来消元。这就是其时间复杂度由来。
例题
模板题。不需要判断无解或无穷解,只要碰到某元系数为0,即可跳出。
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
| #include <iostream> #include <iomanip> #include <cmath> using namespace std;
double matrix[100][101];
int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
int N(0); cin >> N; for (int i(0); i != N; ++i) for (int j(0); j <= N; ++j) cin >> matrix[i][j]; for (int i(0); i != N; ++i) { int mx(i); for (int j(i + 1); j != N; ++j) if (fabs(matrix[j][i]) > fabs(matrix[mx][i])) mx = j; if (i != mx) swap(matrix[i], matrix[mx]); if (!matrix[i][i]) { cout << "No Solution" << endl; return 0; } for (int j(0); j != N; ++j) { if (j != i) { double quot(matrix[j][i] / matrix[i][i]); for (int k(0); k <= N; ++k) { matrix[j][k] -= matrix[i][k] * quot; } } } } for (int i(0); i != N; ++i) { cout << setprecision(2) << fixed << matrix[i][N] / matrix[i][i] << endl; }
return 0; }
|
其实也是模板,比上一个模板更细一些。注意细节!
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
| #include <iostream> #include <iomanip> #include <cmath> using namespace std;
double matrix[50][51];
int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int N(0); cin >> N; for (int i(0); i != N; ++i) for (int j(0); j <= N; ++j) cin >> matrix[i][j]; int cur(0); for (int i(0); i != N; ++i) { int mx(cur); for (int j(cur + 1); j != N; ++j) if (fabs(matrix[j][i]) > fabs(matrix[mx][i])) mx = j; if (!matrix[mx][i]) continue; if (cur != mx) swap(matrix[cur], matrix[mx]); for (int j(0); j != N; ++j) { if (j != cur) { double quot(matrix[j][i] / matrix[cur][i]); for (int k(0); k <= N; ++k) { matrix[j][k] -= matrix[cur][k] * quot; } } } ++cur; } if (cur != N) { while (cur != N) if (matrix[cur++][N]) { cout << -1 << endl; return 0; } cout << 0 << endl; return 0; } for (int i(0); i != N; ++i) { cout << 'x' << i + 1 << '=' << setprecision(2) << fixed << matrix[i][N] / matrix[i][i] << endl; }
return 0; }
|