浅谈高斯-约旦消元法
适用场景
高斯-约旦消元用于解线性方程组,其参考了数学中解方程组的过程。
具体过程
顺次枚举 \(x_1\sim x_n\) 作为主元。对于未知数 \(x_i\),将当前系数最大的方程移到第 \(i\) 的位置,然后将 \(n\) 个方程(除了第 \(i\) 个方程)的 \(x_i\) 的系数都变为 \(0\),这个过程可以通过加减消元来解决。注意我们只用每个方程中 \(x_i\sim x_n\) 的系数,因为 \(x_1\sim x_{i-1}\) 的系数已经被处理完了。最后方程组会形成形如 \(k_ix_i=v_i,1\le i\le n\)。对于每个 \(x_i\) 求出其解即可。
如果最后存在某一行系数都为 \(0\),就说明并不是唯一解。根据 \(v_i\) 是否为 \(0\) 判断是无解还是无穷解。
代码
#include<cmath>
#include<cstdio>
#include<algorithm>
#define N 105
#define db double
using namespace std;
int n;
db a[N][N];
int main()
{
scanf("%d",&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 mx=i;
for (int j=i+1;j<=n;++j)
if (fabs(a[j][i])>fabs(a[mx][i])) mx=j;
for (int j=1;j<=n+1;++j)
swap(a[i][j],a[mx][j]);
if (!a[i][i])
{
printf("No Solution\n");
return 0;
}
for (int j=1;j<=n;++j)
if (i!=j)
{
db t=a[j][i]/a[i][i];
for (int k=i;k<=n+1;++k)
a[j][k]-=a[i][k]*t;
}
}
for (int i=1;i<=n;++i)
printf("%.2lf\n",a[i][n+1]/a[i][i]);
return 0;
}