前往:我自己搭建的博客
题目
洛谷P3389高斯消元法
题解
通过初等行变换把增广矩阵变为简化阶梯形矩阵的线性方程组求解算法就是高斯消元算法。
算法流程:先将方程组写成一个增广矩阵。
然后是加减消元操作,一共进行n次。在第i次操作中,要将第i+1~n行的方程的xi的系数消为0。具体消系数的方法:假设第i行为a*x+c*y=e,要消的某一行为b*x+d*y=f,则b-=(b/a)*a,d-=(b/a)*c,f-=(b/a)*e。在第i次操作进行前,先要将i+1~n行中系数绝对值最大的方程与第i个方程交换位置,这样可以减小误差(原因玄学)而且可以避免当前行的xi系数为0。如果此时第i~n行的式子中xi系数全为0,那么方程组就有无穷多组解。
加减消元操作结束后,会得到一个上三角阶梯型矩阵。
接着是代入消元,可以发现,下面的方程比上面的方程更容易解,于是从n~1依次解元,并利用下面方程已经解得的值,消去当前方程中一些元的系数。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100+5;
const double eps=1e-6; //误差范围
int n;
double a[maxn][maxn];
inline void gauss()
{
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;
if(fabs(a[mx][i])<=eps) {printf("No Solution"); return;}
if(mx!=i) for(int j=i;j<=n+1;j++) swap(a[i][j],a[mx][j]);
for(int j=i+1;j<=n;j++)
for(int k=n+1;k>=i;k--) //逆序循环,确保a[j][i]/a[i][i]是正确的
a[j][k]-=a[j][i]/a[i][i]*a[i][k];
}
for(int i=n;i>=1;i--) //代入消元
{
for(int j=i+1;j<=n;j++) a[i][n+1]-=a[i][j]*a[j][n+1];
a[i][n+1]/=a[i][i]; //不用修改其它系数,因为不影响答案和后续操作
}
for(int i=1;i<=n;i++) printf("%.2lf\n",a[i][n+1]);
}
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]);
gauss();
return 0;
}