高斯消元是一个用来求解多元一次方程的算法,它求解 元一次方程的时间复杂度是 。
做法
我们考虑这样的一个三元一次方程组:
把每一条方程的未知数补全:
然后我们就可以不关心具体的未知数了,只用关心系数。方程组也就可以写成一个矩阵:
其中前三列表示系数,最后一列是方程右边的常数。
考虑方程的求解。很明显可以先加减消元,让某个方程只剩下一个未知数。再代入消元,求出所有未知数。
首先我们让矩阵第三行的方程减去第一行的方程,消掉 :
然后让矩阵第三行的方程减去 倍的第二行的方程,消掉 :
接下来我们就可以求出 的值了,然后再一步一步往回代,就可以解出所有未知数了。
模板题代码如下:
#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;
}
