用途
高斯消元,顾名思义,是用来消元的。
它用来消线性方程组中的元。
实现
其实,高斯消元的本质就是我们小学学的加减消元和代入消元。由于其做法之暴力,它的时间复杂度是 O(n3)O(n^3)O(n3) 的。
具体做法:
假设我们现在有 nnn 个方程,含有 nnn 个未知数,用它们的系数和值造一个矩阵,就是这个样子的:
(a1,1a1,2a1,3⋯a1,nw1a2,1a2,2a2,3⋯a2,nw2⋮⋱an,1an,2an,3⋯an,nw3) \left( \begin{array}{c} a_{1,1} & a_{1,2} & a_{1,3} & \cdots & a_{1,n} & w_1\\ a_{2,1} & a_{2,2} & a_{2,3} & \cdots & a_{2,n} & w_2\\ \vdots & & \ddots\\ a_{n,1} & a_{n,2} & a_{n,3} & \cdots & a_{n,n} & w_3 \end{array} \right) ⎝⎜⎜⎜⎛a1,1a2,1⋮an,1a1,2a2,2an,2a1,3a2,3⋱an,3⋯⋯⋯a1,na2,nan,nw1w2w3⎠⎟⎟⎟⎞
那么,接下来利用 a1,1a_{1,1}a1,1 这个系数,可以将下面 222 ~ nnn 个方程中的第一个未知数消掉,也就是将它们的系数化为 000。
为了方便,首先将 a1,1a_{1,1}a1,1 系数化 111,矩阵就变成了这个样子:
(1a1,2a1,1a1,3a1,1⋯a1,na1,1w1a1,1a2,1a2,2a2,3⋯a2,nw2⋮⋱an,1an,2an,3⋯an,nwn)
\left(
\begin{array}{c}
1 & \frac {a_{1,2}} {a_{1,1}} & \frac {a_{1,3}} {a_{1,1}} & \cdots & \frac {a_{1,n}} {a_{1,1}} & \frac {w_1} {a_{1,1}}\\
a_{2,1} & a_{2,2} & a_{2,3} & \cdots & a_{2,n} & w_2\\
\vdots & & \ddots\\
a_{n,1} & a_{n,2} & a_{n,3} & \cdots & a_{n,n} & w_n
\end{array}
\right)
⎝⎜⎜⎜⎛1a2,1⋮an,1a1,1a1,2a2,2an,2a1,1a1,3a2,3⋱an,3⋯⋯⋯a1,1a1,na2,nan,na1,1w1w2wn⎠⎟⎟⎟⎞
那么要使第 iii 个方程中的第一个未知数的系数化为 000,那么就将第一个方程乘上 ai,1a_{i,1}ai,1,然后相减即可。
做完这一切,222 ~ nnn 个方程中的第一个未知数的系数就都变成 000 了。继续做下去,就可以消得只剩一个未知数,那么就可以将它求出来,依次往回带,就求出了所有未知数的值。
代码:
double matrix[maxn][maxn];
double ans[maxn];
void gauss()
{
for(int i=1;i<=n;i++)
{
int p=i;//为了保证消元顺利的进行,那么当前的第i个方程的第i个未知数的系数就不能为0
//显然,要是为0了,下面毛线都消不了,于是我们将绝对值最大的那个提到上面,作为第i个方程
for(int j=i+1;j<=n;j++)
if(fabs(matrix[j][i])>fabs(matrix[p][i]))p=j;
if(p!=i)swap(matrix[p],matrix[i]);
for(int j=n+1;j>=i;j--)//将第i个未知数的系数化一
matrix[i][j]/=matrix[i][i];
for(int j=i+1;j<=n;j++)//将下面的方程中第i个未知数的系数消掉
for(int k=n+1;k>=i;k--)//注意枚举顺序
matrix[j][k]-=matrix[i][k]*matrix[j][i];
}
ans[n]=matrix[n][n+1];//代回去求解
for(int i=n-1;i>=1;i--)
{
ans[i]=matrix[i][n+1];
for(int j=i+1;j<=n;j++)
ans[i]-=matrix[i][j]*ans[j];
}
}
注意
如果出现某一个方程的系数全部为 000,那么说明方程组是无解或无数解的,这取决于那个方程的值。如果那个方程的值不为 000,就是无解,如果为 000,就是无数解。