浅谈高斯消元
模板题:P3389 【模板】高斯消元法
本文采用高斯-约旦消元法(英语:Gauss-Jordan Elimination)。
相较传统的高斯消元,它不需要回代的过程,所以比较方便。
高斯消元通常用于求解 $n$ 元线性方程组的解(或返回无解),下面是 $n=3$ 的例子
我们可以把它写成矩阵的形式
一般地,考虑 $n$ 元线性方程组
其矩阵形式为
依次考虑每个 $a_{ii}$ ,将除第 $i$ 行的每一行第 $i$ 列都变为 $0$ 。
具体操作为,对于每个 $a_{jk}$ ,使其变为 $a_{jk} - a_{ik} \times \frac{a_{ji}}{a_{ii}}$ 。
最后 $x_i$ 的解就是 $\frac{b_i}{a_{ii}}$ ,且最后的矩阵应该长这样(空白处为 $0$ )
实现时有一些细节,每次把第 $i \sim n$ 行的第 $i$ 列的系数最大值找出来
把它与第 $i$ 行交换,这样可以保证算法的稳定性。(如果最后 $a_{ii}=0$ 则无解)
时间复杂度 $\mathcal{O}(n^3)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(150))
const double eps = 1e-10;
int dcmp(int x)
{
if(abs(x) <= eps) return 0;
return x > eps ? 1 : -1;
}
int n; double a[N][N];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cout << fixed << setprecision(2);
cin >> n;
for(int i=1; i<=n; i++)
for(int j=1; j<=n+1; j++)
cin >> a[i][j];
for(int i=1; i<=n; i++) // col
{
int p = i;
for(int j=i+1; j<=n; j++)
if(abs(a[j][i]) > abs(a[p][i])) p=j; // row
for(int j=1; j<=n+1; j++)
swap(a[i][j],a[p][j]); // swap p to i for proc
if(!dcmp(a[i][i])) return cout << "No Solution\n",0;
for(int j=1; j<=n; j++)
if(j != i)
{
double tmp = a[j][i] / a[i][i];
for(int k=1; k<=n+1; k++)
a[j][k] -= a[i][k] * tmp;
}
}
for(int i=1; i<=n; i++)
cout << a[i][n+1] / a[i][i] << '\n';
return 0;
}
参考文献: