被学长教会的高斯消元法Gauss
昨天学长教了我高斯消元法。
这里用一个栗子来模拟一下Gauss的流程。
真的通俗易懂!这里是洛谷题目链接。
这就是例子
x-2y+3z=6 4x-5y+6z=12 7x-8y+10z=21
先将它转化为矩阵
1 -2 3 6 4 -5 6 12 7 -8 10 21
解决这个方程组
我们会希望它变成如下形式
1 0 0 a 0 1 0 b 0 0 1 c
这样就可以表示为$x=a$,$y=b$,$z=cx=a$,$y=b$,$z=c$,$x=a$,$y=b$,$z=c$
我们使用高斯消元,就要一步一步将每个未知数约去。
这种方法是以列为单位消去的
首先我们将第一列转化为1 0 0的形式
在这里要注意一下,我们往往是将这个系数绝对值最大的方程转移到被减的这一行,这样就可以减小误差
所以我们先将矩阵变成这样
7 -8 10 21 4 -5 6 12 1 -2 3 6
然后将正在处理的方程式化简,让正被处理的系数化1
1 -8/7 10/7 3 4 -5 6 12 1 -2 3 6
然后使用加减法将第二个与第三个方程组的第一个系数化0
1 -8/7 10/7 3 0 -3/7 2/7 0 0 -6/7 11/7 3
然后这时候第一列就被化简完成
同理我们化去第二行与第三行,步骤如下:
1.化简第二行
1 -8/7 10/7 3 0 1 -2/3 0 0 -6/7 11/7 3
2.用第一行减第二行×(-8/7),第三行减第二行×(-6/7)
1 0 2/3 3 0 1 -2/3 0 0 0 1 3
3.不需要化简第三行,所以直接用第一行减去第三行×2/3,第二行减去第三行×(-2/3)
1 0 0 1 0 1 0 2 0 0 1 3
最后我们就得到了一组解x=1,y=2,y=3x=1,y=2,y=3x=1,y=2,y=3 。
所以高斯消元其实是运用了小学解方程组的加减法的讷。
代码请见我的博客《从2017年暑假到现在手打的模板↑_↑》之三十二。
。
。
。
我还是老老实实地贴了上来:
//Guss #include <bits/stdc++.h> using namespace std; int n; double f[105][105]; const double eps=1e-8; int main() { scanf("%d",&n); for (int i=0;i<n;i++)//读入系数和值 for (int j=0;j<=n;j++) scanf("%lf",&f[i][j]); for (int i=0;i<n;i++) { int ch=i; for (int j=i;j<n;j++)//选择绝对值最大的减少误差 if (fabs(f[j][i]-f[ch][i])<=eps) ch=j; for (int j=0;j<=n;j++) swap(f[i][j],f[ch][j]);//交换 if (fabs(f[i][i])<=eps) {//无解情况 printf("No Solution\n"); return 0;//如果当前位置为零 则无解 0x=A } for (int j=i+1;j<=n;j++) f[i][j]/=f[i][i];//系数化1 //自己那位不必要除 无影响 for (int j=0;j<n;j++) if (i!=j) for (int k=i+1;k<=n;k++) f[j][k]-=f[j][i]*f[i][k]; //加减法去掉系数值 } for (int i=0;i<n;i++) printf("%.2lf\n",f[i][n]);//输出 return 0; }