高斯消元学习笔记
前言
高斯消元这么基础的东西,我居然整个初中都没学。
趁现在(19.7.9)赶紧学一下
正文
高斯消元简介
高斯消元是一种用来求解线性方程组(多元一次方程组)的算法。
时间复杂度为O(\(n^3\))
算法流程
枚举当前需要消去的未知数(如x),选择一个式子,用这个式子消去其他式子中的x,重复这个过程直至最后一个方程只有一个未知数(如z),这样就可以方便地计算出z的值,再往回带入算出y,x的值。
注意事项
枚举消去某个未知数时,要选择这个未知数系数最大的那个式子消去其他式子。这样可以减少误差。
假设我们现在在处理第n个未知数,此时在众多的未知数n中,他们的系数分别是\(k_1 k_2 k_3 k_ 4……k_m\),那么考虑,在选完\(k_i\)之后,下面我们要进行的是把\(k_i\)消成1。那么此时对于第i行的其他的系数以及结果我们都要除以\(k_i\)。
之后呢?之后我们要进行的操作是用这个式子来消掉其他式子里的该未知数啊qwq。如果要这么操作肯定会让其他式子别的未知数的系数,减去当前式子的别的未知数的系数乘上某个值(事实上假设选择含\(k_i\)的式子,则对于每个式子j而言,每个系数减去当前系数的倍数,这个倍数应该为$ k_j $)
那么这样看来,对于当次用来消元的式子的每个系数\(q_{i_1}q_{i_2}q_{i_3}q_{i_4}……q_{i_w}\)(假设当前元的系数是\(q_{i_1}\))而言,对于每一个其他式子的该项系数\(q_{jw}\),都需要让\(q_{jw}\)变成
\(q_{jw}-\frac{q_{j1}}{q_{i1}} \times q_{iw}\)
那么我们观察这个式子,\(q_{i1}\)越大,\(\frac{q_{j1}}{q_{i1}}\)期望越小,那么我们考虑,这个值越小,我们就约可以把它看作一个“基本单位”。从而我们就使得减出来的值失精程度越低,最后即可保证数据是从期望上来讲最精确。
By _pks 'w blog
代码实现
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,i,j,k,pick; long double a[105][105],xs,ans[105],anss; int main() { freopen("read.in","r",stdin); scanf("%d",&n); for (i=1;i<=n;i++) { for (j=1;j<=n+1;j++) scanf("%Lf",&a[i][j]); } for (i=1;i<=n;i++) { pick=i; for (j=i;j<=n;j++) if (a[j][i]>a[pick][i]) pick=j; for (j=1;j<=n+1;j++) swap(a[i][j],a[pick][j]); if (a[i][i]==0) continue; for (j=i+1;j<=n;j++) { // printf("%d\n",j); xs=a[j][i]/a[i][i]; for (k=1;k<=n+1;k++) { a[j][k]=a[j][k]-a[i][k]*xs; } } } for (i=n;i>=1;i--) { if (a[i][i]==0) { anss=1; break; } ans[i]=a[i][n+1]/a[i][i]; for (j=i-1;j>=1;j--) { a[j][n+1]=a[j][n+1]-a[j][i]*ans[i]; a[j][i]=0; } } if (anss) printf("No Solution"); else { for (i=1;i<=n;i++) { printf("%.2Lf\n",ans[i]); } } }