高斯消元是一个用来求解多元一次方程的算法,它求解 元一次方程的时间复杂度是 。
做法
我们考虑这样的一个三元一次方程组:
把每一条方程的未知数补全:
然后我们就可以不关心具体的未知数了,只用关心系数。方程组也就可以写成一个矩阵:
其中前三列表示系数,最后一列是方程右边的常数。
考虑方程的求解。很明显可以先加减消元,让某个方程只剩下一个未知数。再代入消元,求出所有未知数。
首先我们让矩阵第三行的方程减去第一行的方程,消掉 :
然后让矩阵第三行的方程减去 倍的第二行的方程,消掉 :
接下来我们就可以求出 的值了,然后再一步一步往回代,就可以解出所有未知数了。
模板题代码如下:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const long long MS=105;
const double zeo=0.0001;
int n;
double a[MS][MS],res[MS];
inline bool slove()
{
// 加减消元过程
for(int i=1;i<=n;i++) // 枚举每一个方程,用第 i 个方程消去未知数 x[i]
{
if(fabs(a[i][i])<=zeo) // 如果当前这个方程不含未知数 x[i](系数为 0),那么去找一个含有它的方程交换一下
{
bool f=false; // 是否能找到
for(int j=i+1;j<=n;j++)
{
if(fabs(a[j][i])>zeo) // 找到了
{
for(int k=1;k<=n+1;k++) // 交换
{
swap(a[i][k],a[j][k]);
}
f=true;
break;
}
}
if(!f) // 条件不足,无法解出方程
{
return false;
}
}
for(int j=i+1;j<=n;j++) // 消去后面的方程中的未知数 x[i]
{
double bs=a[j][i]/a[i][i]; // 第 j 个方程需要减去第 i 个方程的 bs 倍
for(int k=1;k<=n+1;k++) // 减去
{
a[j][k]-=a[i][k]*bs;
}
}
}
// 代入消元过程
for(int i=n;i>=1;i--)
{
for(int j=i+1;j<=n;j++) // x[i+1...n] 已经计算完成,直接代入
{
a[i][n+1]-=a[i][j]*res[j];
}
res[i]=a[i][n+1]/a[i][i]; // 消完元后只剩下 x[i],可以直接求出
}
return true;
}
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]);
}
}
if(!slove())
{
puts("No Solution");
return 0;
}
for(int i=1;i<=n;i++)
{
printf("%.2lf\n",res[i]);
}
return 0;
}