Loading

高斯-约旦消元法 复习笔记

前言

没有什么意外,发现学过的东西又忘了。
我真的是 AH 第一没脑子选手。

正题

相对于传统的高斯消元,约旦消元法的精度更好、代码更简单,没有回带的过程。——某洛谷博客

算法流程

约旦消元法大致思路如下:

  1. 选择一个尚未被选过的未知数作为主元,选择一个包含这个主元的方程。
  2. 将这个方程主元的系数化为1。
  3. 通过加减消元,消掉其它方程中的这个未知数。
  4. 重复以上步骤,直到把每一行都变成只有一项有系数。

算法验证

先随便列一个方程组:

\[\begin{cases} 3x+y+3z=6\\ -2x+7y+8z=17\\ 9x-7y+2z=20\\ \end{cases} \]

高斯-约旦消元 的方法接触当前方程的解。

  • 先把方程组转化成为矩阵的形式。
    以上文的方程组为例,我们列出这样的一个矩阵:

\[\begin{bmatrix} 3 & 1 & 3 & 6\\ -2& 7 & 8 & 17\\ 9 &-7 & 2 & 20\\ \end{bmatrix} \]

  • 看第一列,从上到下扫描,发现绝对值更大的就直接交换。

\[\begin{bmatrix} 3 & 1 & 3 & 6\\ -2& 7 & 8 & 17\\ 9 &-7 & 2 & 20\\ \end{bmatrix} \rightarrow \begin{bmatrix} 9 &-7 & 2 & 20\\ -2& 7 & 8 & 17\\ 3 & 1 & 3 & 6\\ \end{bmatrix} \]

  • 然后运用消元的办法消元就可以了捏。(太懒了不想再算这种申必的系数)
  • 之后的直接重复上面的两步就可以了。

最后会变成一个类似这样的东西:

\[\begin{bmatrix} a_{1,1} &0 & 0 & a\\ 0& a_{2,2} & 0 & b\\ 0 & 1 & a_{3,3} & c\\ \end{bmatrix} \]

直接算就好了。

注意:当出现有一列全部为零时,说明无解。

Code

#include <bits/stdc++.h>

#define file(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)

#define Enter putchar('\n')
#define quad putchar(' ')

#define N 1005

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

signed main(void) {
  // file("P3389");
  std::cin >> n;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n + 1; j++)
      scanf("%lf", &a[i][j]);
  
  for (int i = 1; i <= n; i++) {
    int maxn = i;
    for (int j = i + 1; j <= n; j++)
      if (fabs(a[j][i]) > fabs(a[maxn][i])) maxn = j;
    for (int j = 1; j <= n + 1; j++)
      std::swap(a[i][j], a[maxn][j]);
    if (!a[i][i]) {printf("No Solution\n"); return 0;}
    for (int j = 1; j <= n; j++) {
      if (j == i) continue;
      double tmp = a[j][i] / a[i][i];
      for(int k= i + 1; k <= n + 1; k++)
        a[j][k] -= a[i][k] * tmp;
    }
  }

  for (int i = 1; i <= n; i++)
    printf("%.2lf\n", a[i][n + 1] / a[i][i]);
}
posted @ 2022-04-17 15:50  Aonynation  阅读(80)  评论(0编辑  收藏  举报